sync: Inventory-Realabgleich + neue host_vars/roles/playbooks
Nachgezogener Arbeitsstand des Homelabs: - neue host_vars (k3s-*, gluster-*, docmost, paperless, kometa, thelounge, satisfactory, wolfstack-vm) - neue Rollen/Playbooks (net_watchdog, patchmon-agent, tc_ratelimit, sops-age, rotate-ssh-key, dns-doh, remove-postfix, checkrr-deploy) - diverse Rollen-Updates (base, borg, dns_resolver, frp_client, hawser, nvidia) Ausgeklammert (bleiben uncommittet): host_vars/docmost/vars.yml (Klartext-Token -> sollte vault-konform via vault_* referenziert werden). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
d857b72cf8
commit
bc765668a6
52 changed files with 780 additions and 222 deletions
|
|
@ -9,11 +9,19 @@
|
|||
regexp: '^127\.0\.1\.1'
|
||||
line: "127.0.1.1 {{ inventory_hostname }}.local {{ inventory_hostname }}"
|
||||
|
||||
- name: Prüfe ob Benutzer {{ base_user }} existiert
|
||||
getent:
|
||||
database: passwd
|
||||
key: "{{ base_user }}"
|
||||
register: base_user_check
|
||||
ignore_errors: yes
|
||||
|
||||
- name: SSH Public Key für Benutzer {{ base_user }} hinterlegen
|
||||
ansible.posix.authorized_key:
|
||||
user: "{{ base_user }}"
|
||||
state: present
|
||||
key: "{{ vault_ssh_pubkey }}"
|
||||
when: base_user_check is succeeded
|
||||
|
||||
- name: SSH Private Key für Benutzer {{ base_user }} deployen
|
||||
copy:
|
||||
|
|
@ -22,6 +30,7 @@
|
|||
owner: "{{ base_user }}"
|
||||
group: "{{ base_user }}"
|
||||
mode: "0600"
|
||||
when: base_user_check is succeeded
|
||||
|
||||
- name: SSH Public Key Datei für Benutzer {{ base_user }} deployen
|
||||
copy:
|
||||
|
|
@ -30,6 +39,7 @@
|
|||
owner: "{{ base_user }}"
|
||||
group: "{{ base_user }}"
|
||||
mode: "0644"
|
||||
when: base_user_check is succeeded
|
||||
|
||||
- name: SSH Key auch für root hinterlegen
|
||||
ansible.posix.authorized_key:
|
||||
|
|
@ -85,24 +95,28 @@
|
|||
name: locales
|
||||
state: present
|
||||
|
||||
- name: en_US.UTF-8 Locale generieren
|
||||
- name: de_DE.UTF-8 Locale generieren
|
||||
locale_gen:
|
||||
name: en_US.UTF-8
|
||||
name: de_DE.UTF-8
|
||||
state: present
|
||||
|
||||
- name: Systemweite Sprache auf en_US.UTF-8 setzen
|
||||
- name: Systemweite Sprache auf de_DE.UTF-8 setzen
|
||||
debconf:
|
||||
name: locales
|
||||
question: locales/default_environment_locale
|
||||
value: en_US.UTF-8
|
||||
value: de_DE.UTF-8
|
||||
vtype: select
|
||||
|
||||
- name: Locale-Datei manuell schreiben (Sicherheitsnetz)
|
||||
copy:
|
||||
dest: /etc/default/locale
|
||||
content: |
|
||||
LANG=en_US.UTF-8
|
||||
LC_ALL=en_US.UTF-8
|
||||
LANG=de_DE.UTF-8
|
||||
LC_ALL=de_DE.UTF-8
|
||||
|
||||
- name: Zeitzone auf Europe/Berlin setzen
|
||||
timezone:
|
||||
name: Europe/Berlin
|
||||
|
||||
- name: Gruppe sudo passwortloses sudo erlauben
|
||||
lineinfile:
|
||||
|
|
@ -117,6 +131,7 @@
|
|||
name: "{{ base_user }}"
|
||||
groups: sudo
|
||||
append: yes
|
||||
when: base_user_check is succeeded
|
||||
|
||||
- name: Unnötige Pakete entfernen
|
||||
apt:
|
||||
|
|
@ -126,9 +141,11 @@
|
|||
apt:
|
||||
name: qemu-guest-agent
|
||||
state: present
|
||||
ignore_errors: yes
|
||||
|
||||
- name: QEMU Guest Agent aktivieren
|
||||
service:
|
||||
name: qemu-guest-agent
|
||||
state: started
|
||||
enabled: yes
|
||||
ignore_errors: yes
|
||||
|
|
|
|||
|
|
@ -28,8 +28,27 @@ before_backup:
|
|||
|
||||
after_backup:
|
||||
- curl -fsS -m 10 "https://status.guck.tv/api/push/borg-{{ inventory_hostname }}?status=up&msg=OK&ping=" || true
|
||||
- curl -fsS -m 10 "http://10.1.1.111:9999/push?host={{ inventory_hostname }}&status=ok" || true
|
||||
- >-
|
||||
bash -c '
|
||||
STATS=$(borgmatic info --archive latest --json 2>/dev/null | python3 -c "
|
||||
import sys,json
|
||||
d=json.load(sys.stdin)[0][\"archives\"][-1]
|
||||
s=d.get(\"stats\",{})
|
||||
print(json.dumps({
|
||||
\"host\":\"{{ inventory_hostname }}\",
|
||||
\"status\":\"ok\",
|
||||
\"duration_sec\":int(s.get(\"duration\",0)),
|
||||
\"original_size\":s.get(\"original_size\",0),
|
||||
\"deduplicated_size\":s.get(\"deduplicated_size\",0),
|
||||
\"compressed_size\":s.get(\"compressed_size\",0),
|
||||
\"nfiles_new\":s.get(\"nfiles\",0)
|
||||
}))" 2>/dev/null || echo "{\"host\":\"{{ inventory_hostname }}\",\"status\":\"ok\"}");
|
||||
curl -fsS -m 10 -X POST -H "Content-Type: application/json" -d "$STATS" "http://10.1.1.111:9999/api/push" || true
|
||||
'
|
||||
|
||||
on_error:
|
||||
- curl -fsS -m 10 "https://status.guck.tv/api/push/borg-{{ inventory_hostname }}?status=down&msg=FEHLER&ping=" || true
|
||||
- curl -fsS -m 10 "http://10.1.1.111:9999/push?host={{ inventory_hostname }}&status=error&msg=Backup%20fehlgeschlagen" || true
|
||||
- >-
|
||||
curl -fsS -m 10 -X POST -H "Content-Type: application/json"
|
||||
-d '{"host":"{{ inventory_hostname }}","status":"error","message":"Backup fehlgeschlagen"}'
|
||||
"http://10.1.1.111:9999/api/push" || true
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
---
|
||||
- name: update resolvconf
|
||||
command: resolvconf -u
|
||||
- name: restart dnscrypt-proxy
|
||||
systemd:
|
||||
name: dnscrypt-proxy
|
||||
state: restarted
|
||||
|
|
|
|||
|
|
@ -1,24 +1,16 @@
|
|||
---
|
||||
- name: Set DNS resolver (resolvconf)
|
||||
- name: DNS resolver auf DoH setzen (via automation1)
|
||||
copy:
|
||||
content: |
|
||||
nameserver 10.5.85.5
|
||||
nameserver 1.1.1.1
|
||||
dest: /etc/resolvconf/resolv.conf.d/head
|
||||
mode: '0644'
|
||||
when: ansible_facts.packages is defined and 'resolvconf' in ansible_facts.packages
|
||||
notify: update resolvconf
|
||||
|
||||
- name: Set DNS resolver (direct)
|
||||
copy:
|
||||
content: |
|
||||
nameserver 10.5.85.5
|
||||
nameserver 1.1.1.1
|
||||
dest: /etc/resolv.conf
|
||||
mode: '0644'
|
||||
when: ansible_facts.packages is not defined or 'resolvconf' not in ansible_facts.packages
|
||||
when: inventory_hostname != 'automation1'
|
||||
|
||||
- name: Gather package facts
|
||||
package_facts:
|
||||
manager: auto
|
||||
when: ansible_facts.packages is not defined
|
||||
- name: dnscrypt-proxy stoppen auf VMs (nicht noetig)
|
||||
systemd:
|
||||
name: dnscrypt-proxy
|
||||
state: stopped
|
||||
enabled: false
|
||||
when: inventory_hostname != 'automation1'
|
||||
ignore_errors: true
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@
|
|||
serverPort = {{ frp_server_port }}
|
||||
auth.method = "token"
|
||||
auth.token = "{{ frp_token }}"
|
||||
transport.protocol = "quic"
|
||||
transport.protocol = "tcp"
|
||||
transport.poolCount = 5
|
||||
transport.tcpMux = true
|
||||
{% for proxy in frp_proxies %}
|
||||
|
|
@ -43,8 +43,6 @@
|
|||
localPort = {{ proxy.local_port }}
|
||||
remotePort = {{ proxy.remote_port }}
|
||||
transport.useCompression = true
|
||||
transport.bandwidthLimit = "{{ proxy.bandwidth_limit | default('6MB') }}"
|
||||
transport.bandwidthLimitMode = "server"
|
||||
{% endfor %}
|
||||
mode: "0600"
|
||||
notify: restart frpc
|
||||
|
|
|
|||
|
|
@ -1,14 +1,44 @@
|
|||
---
|
||||
- name: Hawser installieren (offizielles Install-Script)
|
||||
- name: Hawser installieren
|
||||
ansible.builtin.shell:
|
||||
cmd: curl -fsSL https://raw.githubusercontent.com/Finsys/hawser/main/scripts/install.sh | bash
|
||||
cmd: |
|
||||
ARCH=$(dpkg --print-architecture)
|
||||
VERSION=0.2.39
|
||||
curl -fsSL "https://github.com/Finsys/hawser/releases/download/v${VERSION}/hawser_${VERSION}_linux_${ARCH}.tar.gz" | tar xz -C /usr/local/bin hawser
|
||||
chmod +x /usr/local/bin/hawser
|
||||
creates: /usr/local/bin/hawser
|
||||
|
||||
- name: Hawser config Verzeichnis
|
||||
ansible.builtin.file:
|
||||
path: /etc/hawser
|
||||
state: directory
|
||||
|
||||
- name: Hawser Token in Config setzen
|
||||
ansible.builtin.lineinfile:
|
||||
path: /etc/hawser/config
|
||||
regexp: '^TOKEN='
|
||||
line: "TOKEN={{ vault_hawser_token }}"
|
||||
create: yes
|
||||
notify: restart hawser
|
||||
|
||||
- name: Hawser systemd Service
|
||||
ansible.builtin.copy:
|
||||
dest: /etc/systemd/system/hawser.service
|
||||
content: |
|
||||
[Unit]
|
||||
Description=Hawser Agent
|
||||
After=docker.service
|
||||
Requires=docker.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
EnvironmentFile=/etc/hawser/config
|
||||
ExecStart=/usr/local/bin/hawser
|
||||
Restart=always
|
||||
RestartSec=10
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
notify: restart hawser
|
||||
|
||||
- name: Hawser aktivieren und starten
|
||||
|
|
|
|||
23
roles/net_watchdog/defaults/main.yml
Normal file
23
roles/net_watchdog/defaults/main.yml
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
---
|
||||
watchdog_iface: "ens192"
|
||||
watchdog_subnet: "10.5.85.0/24"
|
||||
watchdog_cron_interval: "*/5"
|
||||
watchdog_webhook_url: "{{ vault_watchdog_webhook_url | default('') }}"
|
||||
|
||||
# Bekannte Hosts im Management-Netz (MAC|IP|Name)
|
||||
# Bei neuer VM/Host: hier eintragen + ./pfannkuchen.sh watchdog
|
||||
watchdog_known_hosts:
|
||||
- { mac: "c8:4f:86:fc:00:09", ip: "10.5.85.1", name: "Gateway/Switch" }
|
||||
- { mac: "00:11:32:45:79:28", ip: "10.5.85.10", name: "Synology NAS" }
|
||||
- { mac: "00:50:56:9a:24:35", ip: "10.5.85.5", name: "automation1" }
|
||||
# Proxmox Nodes
|
||||
- { mac: "e4:3d:1a:3c:62:9a", ip: "10.5.85.11", name: "node1" }
|
||||
- { mac: "00:1b:21:de:10:95", ip: "10.5.85.12", name: "node2" }
|
||||
- { mac: "e4:3d:1a:3c:57:6c", ip: "10.5.85.13", name: "node3" }
|
||||
- { mac: "2c:ea:7f:a8:a5:9f", ip: "10.5.85.14", name: "node4" }
|
||||
- { mac: "2c:ea:7f:a8:a9:3f", ip: "10.5.85.15", name: "node5" }
|
||||
- { mac: "e4:3d:1a:3c:3f:a8", ip: "10.5.85.16", name: "node6" }
|
||||
- { mac: "e4:3d:1a:3c:88:da", ip: "10.5.85.17", name: "node7" }
|
||||
# Kubernetes VMs (shared MAC = normal bei Proxmox VMs auf gleichem Node)
|
||||
- { mac: "7a:e8:f0:11:96:20", ip: "10.5.85.101", name: "kube-work1" }
|
||||
- { mac: "7a:e8:f0:11:96:20", ip: "10.5.85.103", name: "kube-ctrl" }
|
||||
18
roles/net_watchdog/tasks/main.yml
Normal file
18
roles/net_watchdog/tasks/main.yml
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
---
|
||||
- name: arp-scan installieren
|
||||
ansible.builtin.apt:
|
||||
name: arp-scan
|
||||
state: present
|
||||
|
||||
- name: Watchdog Script deployen
|
||||
ansible.builtin.template:
|
||||
src: net-watchdog.sh.j2
|
||||
dest: /usr/local/bin/net-watchdog.sh
|
||||
mode: "0755"
|
||||
|
||||
- name: Cronjob einrichten
|
||||
ansible.builtin.cron:
|
||||
name: "net-watchdog"
|
||||
minute: "{{ watchdog_cron_interval }}"
|
||||
job: "/usr/local/bin/net-watchdog.sh --quiet"
|
||||
user: root
|
||||
55
roles/net_watchdog/templates/net-watchdog.sh.j2
Normal file
55
roles/net_watchdog/templates/net-watchdog.sh.j2
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
#!/bin/bash
|
||||
# Network Watchdog – generiert von Ansible
|
||||
# Scannt {{ watchdog_subnet }} auf {{ watchdog_iface }} alle {{ watchdog_cron_interval }}
|
||||
set -euo pipefail
|
||||
|
||||
IFACE="{{ watchdog_iface }}"
|
||||
SUBNET="{{ watchdog_subnet }}"
|
||||
LOGFILE="/var/log/net-watchdog.log"
|
||||
WEBHOOK_URL="{{ watchdog_webhook_url }}"
|
||||
|
||||
# Whitelist (generiert aus Ansible defaults/main.yml)
|
||||
declare -A KNOWN
|
||||
{% for host in watchdog_known_hosts %}
|
||||
KNOWN["{{ host.mac }}|{{ host.ip }}"]="{{ host.name }}"
|
||||
{% endfor %}
|
||||
|
||||
QUIET="${1:-}"
|
||||
|
||||
log() {
|
||||
local msg="$(date '+%Y-%m-%d %H:%M:%S') $1"
|
||||
echo "$msg" >> "$LOGFILE"
|
||||
[ "$QUIET" != "--quiet" ] && echo "$msg"
|
||||
}
|
||||
|
||||
SCAN=$(/usr/sbin/arp-scan --interface="$IFACE" "$SUBNET" 2>/dev/null \
|
||||
| grep -E '^[0-9]+\.' | awk '{print $2"|"$1}')
|
||||
|
||||
UNKNOWN=""
|
||||
ALERT_COUNT=0
|
||||
|
||||
while IFS= read -r line; do
|
||||
[ -z "$line" ] && continue
|
||||
mac=$(echo "$line" | cut -d'|' -f1)
|
||||
ip=$(echo "$line" | cut -d'|' -f2)
|
||||
if [ -z "${KNOWN["${mac}|${ip}"]:-}" ]; then
|
||||
UNKNOWN+="⚠️ ${ip} (MAC: ${mac})\n"
|
||||
log "ALERT: Unbekannter Host ${ip} MAC=${mac}"
|
||||
((ALERT_COUNT++))
|
||||
fi
|
||||
done <<< "$SCAN"
|
||||
|
||||
if [ "$ALERT_COUNT" -gt 0 ]; then
|
||||
log "SCAN: ${ALERT_COUNT} unbekannte Hosts!"
|
||||
if [ -n "$WEBHOOK_URL" ]; then
|
||||
curl -s -X POST "$WEBHOOK_URL" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"event\":\"unknown_host\",\"subnet\":\"${SUBNET}\",\"count\":${ALERT_COUNT},\"details\":\"$(echo -e "$UNKNOWN" | tr '\n' ' ')\",\"timestamp\":\"$(date -Iseconds)\"}" \
|
||||
>/dev/null 2>&1 || log "WARN: Webhook fehlgeschlagen"
|
||||
fi
|
||||
[ "$QUIET" != "--quiet" ] && echo -e "\n${UNKNOWN}"
|
||||
exit 1
|
||||
else
|
||||
log "SCAN: OK – alle $(echo "$SCAN" | wc -l) Hosts bekannt"
|
||||
exit 0
|
||||
fi
|
||||
|
|
@ -44,6 +44,7 @@
|
|||
ansible.builtin.apt:
|
||||
name:
|
||||
- linux-headers-{{ ansible_kernel }}
|
||||
- linux-headers-amd64
|
||||
- dkms
|
||||
state: present
|
||||
|
||||
|
|
|
|||
5
roles/patchmon-agent/handlers/main.yml
Normal file
5
roles/patchmon-agent/handlers/main.yml
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
- name: restart patchmon-agent
|
||||
ansible.builtin.systemd:
|
||||
name: patchmon-agent
|
||||
state: restarted
|
||||
33
roles/patchmon-agent/tasks/main.yml
Normal file
33
roles/patchmon-agent/tasks/main.yml
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
---
|
||||
- name: Prüfen ob patchmon-agent bereits installiert ist
|
||||
ansible.builtin.stat:
|
||||
path: /usr/local/bin/patchmon-agent
|
||||
register: patchmon_bin
|
||||
|
||||
- name: Prüfen ob Agent bereits enrolled ist
|
||||
ansible.builtin.command: /usr/local/bin/patchmon-agent ping
|
||||
register: patchmon_ping
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
when: patchmon_bin.stat.exists
|
||||
|
||||
- name: PatchMon Agent installieren (Auto-Enrollment)
|
||||
ansible.builtin.shell: |
|
||||
curl -sk "https://patchmon.sascha-lutz.de/api/v1/auto-enrollment/script?type=direct-host&token_key={{ vault_patchmon_token_key }}&token_secret={{ vault_patchmon_token_secret }}" | sh
|
||||
args:
|
||||
creates: /etc/patchmon/credentials.yml
|
||||
when: not patchmon_bin.stat.exists or (patchmon_ping.rc is defined and patchmon_ping.rc != 0)
|
||||
|
||||
- name: Server-URL sicherstellen
|
||||
ansible.builtin.lineinfile:
|
||||
path: /etc/patchmon/config.yml
|
||||
regexp: '^patchmon_server:'
|
||||
line: 'patchmon_server: "https://patchmon.sascha-lutz.de"'
|
||||
notify: restart patchmon-agent
|
||||
|
||||
- name: Docker-Integration aktivieren
|
||||
ansible.builtin.lineinfile:
|
||||
path: /etc/patchmon/config.yml
|
||||
regexp: '^\s*docker:'
|
||||
line: ' docker: true'
|
||||
notify: restart patchmon-agent
|
||||
5
roles/tc_ratelimit/defaults/main.yml
Normal file
5
roles/tc_ratelimit/defaults/main.yml
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
tc_iface: "auto"
|
||||
tc_flow_limit: "50mbit"
|
||||
tc_total_limit: "500mbit"
|
||||
tc_burst: "1mb"
|
||||
6
roles/tc_ratelimit/handlers/main.yml
Normal file
6
roles/tc_ratelimit/handlers/main.yml
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
- name: restart tc-ratelimit
|
||||
ansible.builtin.systemd:
|
||||
name: tc-ratelimit
|
||||
state: restarted
|
||||
daemon_reload: true
|
||||
33
roles/tc_ratelimit/tasks/main.yml
Normal file
33
roles/tc_ratelimit/tasks/main.yml
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
---
|
||||
- name: Netzwerk-Interface ermitteln
|
||||
ansible.builtin.shell:
|
||||
cmd: "ip -o link show | awk -F': ' '!/lo/{print $2; exit}'"
|
||||
register: detected_iface
|
||||
changed_when: false
|
||||
when: tc_iface == "auto"
|
||||
|
||||
- name: Interface setzen
|
||||
ansible.builtin.set_fact:
|
||||
tc_iface: "{{ detected_iface.stdout | trim }}"
|
||||
when: tc_iface == "auto"
|
||||
|
||||
- name: tc-ratelimit Script deployen
|
||||
ansible.builtin.template:
|
||||
src: tc-ratelimit.sh.j2
|
||||
dest: /usr/local/bin/tc-ratelimit.sh
|
||||
mode: "0755"
|
||||
notify: restart tc-ratelimit
|
||||
|
||||
- name: Systemd Service deployen
|
||||
ansible.builtin.template:
|
||||
src: tc-ratelimit.service.j2
|
||||
dest: /etc/systemd/system/tc-ratelimit.service
|
||||
mode: "0644"
|
||||
notify: restart tc-ratelimit
|
||||
|
||||
- name: Service aktivieren und starten
|
||||
ansible.builtin.systemd:
|
||||
name: tc-ratelimit
|
||||
enabled: true
|
||||
state: started
|
||||
daemon_reload: true
|
||||
13
roles/tc_ratelimit/templates/tc-ratelimit.service.j2
Normal file
13
roles/tc_ratelimit/templates/tc-ratelimit.service.j2
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
[Unit]
|
||||
Description=tc per-flow rate limit ({{ tc_flow_limit }} per connection)
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
RemainAfterExit=yes
|
||||
ExecStart=/usr/local/bin/tc-ratelimit.sh start
|
||||
ExecStop=/usr/local/bin/tc-ratelimit.sh stop
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
26
roles/tc_ratelimit/templates/tc-ratelimit.sh.j2
Normal file
26
roles/tc_ratelimit/templates/tc-ratelimit.sh.j2
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
#!/bin/bash
|
||||
# tc per-flow rate limit – deployed via Ansible
|
||||
# Jede TCP-Connection bekommt max {{ tc_flow_limit }}
|
||||
IFACE="{{ tc_iface }}"
|
||||
FLOW_LIMIT="{{ tc_flow_limit }}"
|
||||
TOTAL_LIMIT="{{ tc_total_limit }}"
|
||||
BURST="{{ tc_burst }}"
|
||||
|
||||
case "${1}" in
|
||||
start)
|
||||
tc qdisc del dev "${IFACE}" root 2>/dev/null
|
||||
tc qdisc add dev "${IFACE}" root handle 1: htb default 10
|
||||
tc class add dev "${IFACE}" parent 1: classid 1:1 htb rate "${TOTAL_LIMIT}" burst "${BURST}"
|
||||
tc class add dev "${IFACE}" parent 1:1 classid 1:10 htb rate "${TOTAL_LIMIT}" burst "${BURST}"
|
||||
tc qdisc add dev "${IFACE}" parent 1:10 handle 10: fq maxrate "${FLOW_LIMIT}" flow_limit 200
|
||||
echo "tc: ${FLOW_LIMIT}/flow on ${IFACE}"
|
||||
;;
|
||||
stop)
|
||||
tc qdisc del dev "${IFACE}" root 2>/dev/null
|
||||
;;
|
||||
status)
|
||||
tc -s qdisc show dev "${IFACE}"
|
||||
tc -s class show dev "${IFACE}"
|
||||
;;
|
||||
*) echo "Usage: $0 {start|stop|status}"; exit 1 ;;
|
||||
esac
|
||||
Loading…
Add table
Add a link
Reference in a new issue