diff --git a/.gitignore b/.gitignore index d513b9e..afb6b4c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .*.swp __pycache__ +files/ssh/backup.pub diff --git a/container-ports.md b/container-ports.md new file mode 100644 index 0000000..25fcc97 --- /dev/null +++ b/container-ports.md @@ -0,0 +1,16 @@ +# Ports used by container web services + +| Port | Ansible role | Service name | +|------|---------------------|----------------------------| +| 8001 | kerberos_kdc | Kerberos KDC | +| 8002 | grafana | Grafana | +| 8003 | authcheck | Authentication check | +| 8004 | roundcube | Roundcube webmail | +| 8005 | php4dvd | php4dvd movie catalog | +| 8006 | scanservjs | SANE Scanner webui | +| 8007 | frigate | Network video recorder | +| 8008 | hoemeassistant | Home Assistant | +| 8009 | rocketchat | Rocket.Chat | +| 8010 | google-spell-pspell | Google Spell Check XML API | +| 8011 | ipsilon | Ipsilon Identity Provider | +| 8012 | nodered | Node Red | diff --git a/files/ssh/backup.pub b/files/ssh/backup.pub deleted file mode 100644 index 336fbc7..0000000 --- a/files/ssh/backup.pub +++ /dev/null @@ -1 +0,0 @@ -ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKdaNO9dLpI8CVx1rwGsKN45Pgiz+Btrlf2Q/nXCx4Ru root@backup02.home.foo.sh diff --git a/group_vars/adm.yml b/group_vars/adm.yml index 0eff70a..a06d51b 100644 --- a/group_vars/adm.yml +++ b/group_vars/adm.yml @@ -1,8 +1,12 @@ --- datadisks: - - {size: 10} + - {size: 10, type: nvme} firewall_in: - {proto: tcp, port: 22, from: [172.20.20.0/22]} + - {proto: tcp, port: 80, from: [172.20.20.0/22]} - {proto: tcp, port: 443, from: [172.20.20.0/22]} - - {proto: tcp, port: 4949, from: [172.20.20.0/22]} + - {proto: tcp, port: 9100, from: [172.20.20.0/22]} + +sssd_allow_groups: + - sysadm diff --git a/group_vars/all.yml b/group_vars/all.yml index 39ac197..13c4354 100644 --- a/group_vars/all.yml +++ b/group_vars/all.yml @@ -31,8 +31,10 @@ boot_url: https://boot.foo.sh # ssh public keys for logsync user logsync_publickeys: "{{ lookup('file', '../files/ssh/logsync.pub') }}" -# ssh public keys for backup user -backup_publickeys: "{{ lookup('file', '../files/ssh/backup.pub') }}" +# default name servers +network_dns_servers: + - 8.8.8.8 + - 8.8.4.4 # hardcode this for now ansible_datacenter: home diff --git a/group_vars/gitea.yml b/group_vars/audiobooks.yml similarity index 62% rename from group_vars/gitea.yml rename to group_vars/audiobooks.yml index 985e033..4fcc30e 100644 --- a/group_vars/gitea.yml +++ b/group_vars/audiobooks.yml @@ -1,8 +1,8 @@ --- datadisks: - - {size: 10, type: hdd} + - {size: 50, type: hdd} firewall_in: - {proto: tcp, port: 22, from: [172.20.20.0/22]} - {proto: tcp, port: 443, from: [172.20.20.0/22]} - - {proto: tcp, port: 4949, from: [172.20.20.0/22]} + - {proto: tcp, port: 9100, from: [172.20.20.0/22]} diff --git a/group_vars/backup.yml b/group_vars/backup.yml index ec4ea73..0b7f509 100644 --- a/group_vars/backup.yml +++ b/group_vars/backup.yml @@ -1,3 +1,4 @@ --- firewall_in: - {proto: tcp, port: 22, from: [172.20.20.0/22]} + - {proto: tcp, port: 9100, from: [172.20.20.0/22]} diff --git a/group_vars/collab.yml b/group_vars/collab.yml index a49673c..e80e98c 100644 --- a/group_vars/collab.yml +++ b/group_vars/collab.yml @@ -5,4 +5,4 @@ datadisks: firewall_in: - {proto: tcp, port: 22, from: [172.20.20.0/22]} - {proto: tcp, port: 443, from: [172.20.20.0/22]} - - {proto: tcp, port: 4949, from: [172.20.20.0/22]} + - {proto: tcp, port: 9100, from: [172.20.20.0/22]} diff --git a/group_vars/dnagw.yml b/group_vars/dnagw.yml index 9b2bacc..fe380e8 100644 --- a/group_vars/dnagw.yml +++ b/group_vars/dnagw.yml @@ -12,12 +12,32 @@ network_vip_interfaces: netmask: 255.255.252.0 pass: "{{ vip10_pass }}" priority: 120 + - device: vio0 + vhid: 11 + ipaddr: 172.20.20.11 + netmask: 255.255.252.0 + pass: "{{ vip11_pass }}" + priority: "{{ vip11_priority }}" + - device: vio0 + vhid: 12 + ipaddr: 172.20.20.12 + netmask: 255.255.252.0 + pass: "{{ vip12_pass }}" + priority: "{{ vip12_priority }}" network_ether_interfaces: - device: vio1 proto: none +unbound_zones: + - 20.172.in-addr.arpa + - home.foo.sh + # use custom firewall config firewall_src: pf.conf.gw_home # ifstated config ifstated_config: ifstated-dna.conf.j2 + +# ssh host alaises +ssh_hostnames: + - gw.home.foo.sh diff --git a/group_vars/fedora.yml b/group_vars/fedora.yml index c0ed1a5..1f7eeea 100644 --- a/group_vars/fedora.yml +++ b/group_vars/fedora.yml @@ -1,7 +1,7 @@ --- # default resources for new vm dsk_size: 20 -mem_size: 2048 +mem_size: 4096 num_cpus: 2 # extra args for virt-install @@ -18,7 +18,7 @@ ipcmd: >- {% endif %} virt_install_os_args: >- --location - https://nic.funet.fi/pub/mirrors/fedora.redhat.com/pub/fedora/linux/releases/38/Everything/x86_64/os/ + https://nic.funet.fi/pub/mirrors/fedora.redhat.com/pub/fedora/linux/releases/41/Everything/x86_64/os/ --extra-args "inst.ks={{ ks_file }} console=ttyS0 diff --git a/group_vars/forgejo.yml b/group_vars/forgejo.yml new file mode 100644 index 0000000..e80e98c --- /dev/null +++ b/group_vars/forgejo.yml @@ -0,0 +1,8 @@ +--- +datadisks: + - {size: 10, type: nvme} + +firewall_in: + - {proto: tcp, port: 22, from: [172.20.20.0/22]} + - {proto: tcp, port: 443, from: [172.20.20.0/22]} + - {proto: tcp, port: 9100, from: [172.20.20.0/22]} diff --git a/group_vars/zm.yml b/group_vars/frigate.yml similarity index 51% rename from group_vars/zm.yml rename to group_vars/frigate.yml index 4da1f4f..81a93e1 100644 --- a/group_vars/zm.yml +++ b/group_vars/frigate.yml @@ -1,8 +1,9 @@ --- -mem_size: 4096 +mem_size: 8192 num_cpus: 2 datadisks: - - {size: 500} + - {size: 50, type: nvme} + - {size: 500, type: hdd} network_vip_interfaces: - device: eth1 @@ -11,13 +12,16 @@ network_vip_interfaces: netmask: 255.255.0.0 pass: "{{ vip26_pass }}" -zm_mysql_host: sqldb02.home.foo.sh +unbound_zones: + - 26.20.172.in-addr.arpa + - cam.foo.sh dhcpd_template: dhcpd.conf.cam.j2 +dhcpd_ldap_filter: >- + (&(objectClass=ieee802Device)(objectClass=ipHost)(cn=*.cam.foo.sh)) firewall_in: - {proto: tcp, port: 22, from: [172.20.20.0/22]} - {proto: tcp, port: 443, from: [172.20.20.0/22]} - - {proto: tcp, port: 4949, from: [172.20.20.0/22]} + - {proto: tcp, port: 9100, from: [172.20.20.0/22]} firewall_raw: - - "-A INPUT -i eth1 -d 224.0.0.0/8 -j ACCEPT" - - "-A INPUT -i eth1 -p vrrp -j ACCEPT" + - "ip daddr 224.0.0.0/8 accept" diff --git a/group_vars/fsolgw.yml b/group_vars/fsolgw.yml index fc3b312..6012a52 100644 --- a/group_vars/fsolgw.yml +++ b/group_vars/fsolgw.yml @@ -4,8 +4,9 @@ network_vip_interfaces: vhid: 145 ipaddr: 37.16.96.145 netmask: 255.255.255.240 + ip6addr: 2a00:4cc1:6:1006::1 + ip6netmask: 64 pass: "{{ vip145_pass }}" -network_dns_servers: [172.20.20.10, 172.20.21.1, 172.20.21.2] # use custom firewall and ifstated config firewall_src: pf.conf.gw_fsol diff --git a/group_vars/gitearunner.yml b/group_vars/gitearunner.yml deleted file mode 100644 index c611eea..0000000 --- a/group_vars/gitearunner.yml +++ /dev/null @@ -1,4 +0,0 @@ ---- -firewall_in: - - {proto: tcp, port: 22, from: [172.20.20.0/22]} - - {proto: tcp, port: 4949, from: [172.20.20.0/22]} diff --git a/group_vars/home.yml b/group_vars/home.yml new file mode 100644 index 0000000..d8558c0 --- /dev/null +++ b/group_vars/home.yml @@ -0,0 +1,5 @@ +--- +network_dns_servers: + - 172.20.20.10 + - 172.20.20.11 + - 172.20.20.12 diff --git a/group_vars/homeassistant.yml b/group_vars/homeassistant.yml index 91f88e0..d344ed1 100644 --- a/group_vars/homeassistant.yml +++ b/group_vars/homeassistant.yml @@ -1,7 +1,7 @@ --- datadisks: - - {size: 10, type: hdd} + - {size: 10, type: nvme} firewall_in: - {proto: tcp, port: 22, from: [172.20.20.0/22]} - {proto: tcp, port: 443, from: [172.20.20.0/22]} - - {proto: tcp, port: 4949, from: [172.20.20.0/22]} + - {proto: tcp, port: 9100, from: [172.20.20.0/22]} diff --git a/group_vars/influxdb.yml b/group_vars/influxdb.yml index fcdcc1b..be5bea6 100644 --- a/group_vars/influxdb.yml +++ b/group_vars/influxdb.yml @@ -5,4 +5,4 @@ datadisks: firewall_in: - {proto: tcp, port: 22, from: [172.20.20.0/22]} - {proto: tcp, port: 443, from: [172.20.20.0/22]} - - {proto: tcp, port: 4949, from: [172.20.20.0/22]} + - {proto: tcp, port: 9100, from: [172.20.20.0/22]} diff --git a/group_vars/ldap.yml b/group_vars/ldap.yml index 660bcb5..1e3e573 100644 --- a/group_vars/ldap.yml +++ b/group_vars/ldap.yml @@ -3,6 +3,5 @@ saslauthd_mech: ldap firewall_in: - {proto: tcp, port: 22, from: [172.20.20.0/22]} - - {proto: tcp, port: 443, from: [172.20.20.0/22]} - {proto: tcp, port: 636, from: [172.20.20.0/22]} - - {proto: tcp, port: 4949, from: [172.20.20.0/22]} + - {proto: tcp, port: 9100, from: [172.20.20.0/22]} diff --git a/group_vars/log.yml b/group_vars/log.yml index 7457482..f7c44ba 100644 --- a/group_vars/log.yml +++ b/group_vars/log.yml @@ -1,8 +1,9 @@ --- +mem_size: 512 datadisks: - - {size: 50} + - {size: 50, type: nvme} firewall_in: - {proto: tcp, port: 22, from: [172.20.20.0/22]} - - {proto: tcp, port: 4949, from: [172.20.20.0/22]} + - {proto: tcp, port: 9100, from: [172.20.20.0/22]} - {proto: tcp, port: 6514} diff --git a/group_vars/mail.yml b/group_vars/mail.yml index 7976023..4de52d0 100644 --- a/group_vars/mail.yml +++ b/group_vars/mail.yml @@ -1,6 +1,7 @@ --- datadisks: - - {size: 10} + - {size: 10, type: nvme} +mem_size: 4192 firewall_in: - {proto: tcp, port: 22, from: [172.20.20.0/22]} @@ -10,4 +11,7 @@ firewall_in: - {proto: tcp, port: 465} - {proto: tcp, port: 587} - {proto: tcp, port: 993} - - {proto: tcp, port: 4949, from: [172.20.20.0/22]} + - {proto: tcp, port: 9100, from: [172.20.20.0/22]} + +sssd_allow_groups: + - sysadm diff --git a/group_vars/minecraft.yml b/group_vars/minecraft.yml index cf60405..a7ff2b1 100644 --- a/group_vars/minecraft.yml +++ b/group_vars/minecraft.yml @@ -1,9 +1,9 @@ --- mem_size: 4096 datadisks: - - {size: 100} + - {size: 100, type: nvme} firewall_in: - {proto: tcp, port: 22, from: [172.20.20.0/22]} - - {proto: tcp, port: 4949, from: [172.20.30.0/24]} + - {proto: tcp, port: 9100, from: [172.20.30.0/24]} - {proto: tcp, port: 25565, from: [172.20.30.0/24]} - {proto: udp, port: 25565, from: [172.20.30.0/24]} diff --git a/group_vars/mirror.yml b/group_vars/mirror.yml index 4ac63b1..c21d751 100644 --- a/group_vars/mirror.yml +++ b/group_vars/mirror.yml @@ -1,10 +1,9 @@ --- - datadisks: - - {size: 1000} + - {size: 1500, type: hdd} firewall_in: - {proto: tcp, port: 22, from: [172.20.20.0/22]} - {proto: tcp, port: 443, from: [172.20.20.0/22]} - {proto: tcp, port: 873, from: [172.20.20.0/22]} - - {proto: tcp, port: 4949, from: [172.20.20.0/22]} + - {proto: tcp, port: 9100, from: [172.20.20.0/22]} diff --git a/group_vars/mongodb.yml b/group_vars/mongodb.yml index e17dd45..656811d 100644 --- a/group_vars/mongodb.yml +++ b/group_vars/mongodb.yml @@ -4,3 +4,4 @@ datadisks: firewall_in: - {proto: tcp, port: 22, from: [172.20.20.0/22]} - {proto: tcp, port: 27017, from: [172.20.20.0/22]} + - {proto: tcp, port: 9100, from: [172.20.20.0/22]} diff --git a/group_vars/mqtt.yml b/group_vars/mqtt.yml index ec10fe7..e64ff98 100644 --- a/group_vars/mqtt.yml +++ b/group_vars/mqtt.yml @@ -3,5 +3,5 @@ firewall_in: - {proto: tcp, port: 22, from: [172.20.20.0/22]} - {proto: tcp, port: 443, from: [172.20.27.0/24]} - {proto: tcp, port: 1883, from: [172.20.27.0/24]} - - {proto: tcp, port: 4949, from: [172.20.20.0/22]} + - {proto: tcp, port: 9100, from: [172.20.20.0/22]} - {proto: tcp, port: 8883, from: [172.20.20.0/22, 172.20.27.0/24]} diff --git a/group_vars/nas.yml b/group_vars/nas.yml index 84be798..5dac726 100644 --- a/group_vars/nas.yml +++ b/group_vars/nas.yml @@ -2,11 +2,14 @@ mem_size: 8192 num_cpus: 2 datadisks: - - {size: 1000} - - {size: 400, type: nvme} + - {size: 500, type: nvme} + - {size: 50, type: nvme} firewall_in: - {proto: tcp, port: 22, from: [172.20.20.0/22]} - {proto: tcp, port: 2049, from: [172.20.20.0/22]} - {proto: tcp, port: 2049, from: [172.20.30.0/24]} - - {proto: tcp, port: 4949, from: [172.20.20.0/22]} + - {proto: tcp, port: 9100, from: [172.20.20.0/22]} + +sssd_allow_groups: + - root diff --git a/group_vars/nms.yml b/group_vars/nms.yml index 83c016a..bd86e46 100644 --- a/group_vars/nms.yml +++ b/group_vars/nms.yml @@ -1,12 +1,24 @@ --- datadisks: - - {size: 10} + - {size: 10, type: nvme} + +unbound_zones: + - 25.20.172.in-addr.arpa + - oob.foo.sh +dhcpd_template: dhcpd.conf.oob.j2 +dhcpd_ldap_filter: >- + (&(objectClass=ieee802Device)(objectClass=ipHost)(cn=*.oob.foo.sh)) network_vip_interfaces: + - device: eth0 + vhid: 11 + ipaddr: 172.20.20.21 + netmask: 255.255.240.0 + pass: "{{ vip21_pass }}" - device: eth1 vhid: 25 ipaddr: 172.20.25.1 - netmask: 255.255.0.0 + netmask: 255.255.255.0 pass: "{{ vip25_pass }}" priority: "{{ vip25_priority }}" @@ -19,7 +31,10 @@ firewall_in: - {proto: udp, port: 123, from: [172.20.25.0/24]} - {proto: tcp, port: 443, from: [172.20.25.0/24]} - {proto: udp, port: 514, from: [172.20.25.0/24]} - - {proto: tcp, port: 4949, from: [172.20.20.0/22]} + - {proto: tcp, port: 9100, from: [172.20.20.0/22]} + - {proto: tcp, port: 9116, from: [172.20.20.0/22]} firewall_raw: - - "-A INPUT -i eth1 -d 224.0.0.0/8 -j ACCEPT" - - "-A INPUT -i eth1 -p vrrp -j ACCEPT" + - "ip daddr 224.0.0.0/8 accept" + +sssd_allow_groups: + - sysadm diff --git a/group_vars/ns.yml b/group_vars/ns.yml index 6542553..2a284b1 100644 --- a/group_vars/ns.yml +++ b/group_vars/ns.yml @@ -1,12 +1,13 @@ --- firewall_in: - - {proto: tcp, port: 22, from: [172.20.20.0/22, 81.175.130.44/32]} + - {proto: tcp, port: 22, from: [172.20.20.0/22, 212.149.225.204/32]} - {proto: tcp, port: 53} - {proto: udp, port: 53} - {proto: tcp, port: 80} - {proto: tcp, port: 443} - {proto: tcp, port: 853} - - {proto: tcp, port: 4949, from: [172.20.20.0/22, 81.175.130.44/32]} + - {proto: tcp, port: 9100} + - {proto: tcp, port: 9115} firewall_raw: - pass quick proto carp diff --git a/group_vars/ocinode.yml b/group_vars/ocinode.yml index 9945015..d66dfb6 100644 --- a/group_vars/ocinode.yml +++ b/group_vars/ocinode.yml @@ -1,7 +1,10 @@ --- # increase memory size -mem_size: 4192 +mem_size: 8192 +# increase disk size to store docker images +dsk_size: 100 firewall_in: - {proto: tcp, port: 22, from: [172.20.20.0/22]} - {proto: tcp, port: 443, from: [172.20.20.0/22]} + - {proto: tcp, port: 9100, from: [172.20.20.0/22]} diff --git a/group_vars/openbsd.yml b/group_vars/openbsd.yml index 51337c9..2695e29 100644 --- a/group_vars/openbsd.yml +++ b/group_vars/openbsd.yml @@ -17,5 +17,5 @@ num_cpus: 2 # extra args for virt-install virt_install_os_args: --cdrom {{ boot_url }}/openbsd/openbsd.iso -virt_install_os_variant: openbsd7.0 -virt_install_python_cmd: pkg_add python3 -I -x +virt_install_os_variant: openbsd7.4 +virt_install_python_cmd: pkg_add -I -x python diff --git a/group_vars/print.yml b/group_vars/print.yml index 7029178..fc2e3fb 100644 --- a/group_vars/print.yml +++ b/group_vars/print.yml @@ -7,14 +7,20 @@ network_vip_interfaces: pass: "{{ vip24_pass }}" priority: "{{ vip24_priority }}" -dhcpd_template: dhcpd.conf.print.j2 - firewall_in: - {proto: tcp, port: 22, from: [172.20.20.0/22]} - {proto: tcp, port: 53, from: [172.20.24.0/24]} - {proto: udp, port: 53, from: [172.20.24.0/24]} - {proto: tcp, port: 631, from: [172.20.20.0/22]} - - {proto: tcp, port: 4949, from: [172.20.20.0/22]} + - {proto: tcp, port: 9100, from: [172.20.20.0/22]} firewall_raw: - - "-A INPUT -i eth1 -d 224.0.0.0/8 -j ACCEPT" - - "-A INPUT -i eth1 -p vrrp -j ACCEPT" + - "ip daddr 224.0.0.0/8 accept" + +dhcpd_template: dhcpd.conf.print.j2 +dhcpd_ldap_filter: >- + (&(objectClass=ieee802Device)(objectClass=ipHost)(cn=*.print.foo.sh)) +sssd_allow_groups: + - sysadm +unbound_zones: + - 24.20.172.in-addr.arpa + - print.foo.sh diff --git a/group_vars/prometheus.yml b/group_vars/prometheus.yml new file mode 100644 index 0000000..be5bea6 --- /dev/null +++ b/group_vars/prometheus.yml @@ -0,0 +1,8 @@ +--- +datadisks: + - {size: 100, type: nvme} + +firewall_in: + - {proto: tcp, port: 22, from: [172.20.20.0/22]} + - {proto: tcp, port: 443, from: [172.20.20.0/22]} + - {proto: tcp, port: 9100, from: [172.20.20.0/22]} diff --git a/group_vars/proxy.yml b/group_vars/proxy.yml index c3ffdcd..ea7cba9 100644 --- a/group_vars/proxy.yml +++ b/group_vars/proxy.yml @@ -4,12 +4,6 @@ mem_size: 1024 # use bigger disk for os as we have web site data there dsk_size: 30 -network_dns_servers: - - 172.20.20.10 - - 172.20.21.7 - - 172.20.21.8 -network_dns_search: - - foo.sh network_default_gateway: 37.16.96.145 network_vip_interfaces: @@ -48,6 +42,4 @@ firewall_in: - {proto: tcp, port: 22, from: [172.20.20.0/22]} - {proto: tcp, port: 80} - {proto: tcp, port: 443} - - {proto: tcp, port: 636} - - {proto: tcp, port: 4949, from: [172.20.20.0/22]} - - {proto: tcp, port: 6514} + - {proto: tcp, port: 9100, from: [172.20.20.0/22]} diff --git a/group_vars/relay.yml b/group_vars/relay.yml index b48a3a2..a52f0b5 100644 --- a/group_vars/relay.yml +++ b/group_vars/relay.yml @@ -1,10 +1,4 @@ --- -network_dns_servers: - - 172.20.20.10 - - 172.20.21.7 - - 172.20.21.8 -network_dns_search: - - foo.sh network_default_gateway: 37.16.96.145 network_vip_interfaces: @@ -41,3 +35,4 @@ firewall_in: - {proto: tcp, port: 443} - {proto: tcp, port: 636} - {proto: tcp, port: 6514} + - {proto: tcp, port: 9100} diff --git a/group_vars/sane.yml b/group_vars/sane.yml new file mode 100644 index 0000000..a6636ac --- /dev/null +++ b/group_vars/sane.yml @@ -0,0 +1,5 @@ +--- +firewall_in: + - {proto: tcp, port: 22, from: [172.20.20.0/22]} + - {proto: tcp, port: 443, from: [172.20.20.0/22]} + - {proto: tcp, port: 9100, from: [172.20.20.0/22]} diff --git a/group_vars/shell.yml b/group_vars/shell.yml index cefac15..6300cab 100644 --- a/group_vars/shell.yml +++ b/group_vars/shell.yml @@ -1,6 +1,4 @@ --- - -# beef up shell hosts dsk_size: 40 mem_size: 8192 num_cpus: 4 @@ -9,4 +7,10 @@ firewall_in: - {proto: tcp, port: 22} - {proto: tcp, port: 80} - {proto: tcp, port: 443} - - {proto: tcp, port: 4949, from: [81.175.130.44/32]} + - {proto: tcp, port: 9100, from: [212.149.248.65/32]} + +ssh_hostnames: + - shell.foo.sh + +sssd_allow_groups: + - foosh diff --git a/group_vars/sqldb.yml b/group_vars/sqldb.yml index df3c506..5848832 100644 --- a/group_vars/sqldb.yml +++ b/group_vars/sqldb.yml @@ -1,6 +1,8 @@ --- +mem_size: 4096 datadisks: - {size: 20, type: nvme} firewall_in: - {proto: tcp, port: 22, from: [172.20.20.0/22]} - {proto: tcp, port: 3306, from: [172.20.20.0/22]} + - {proto: tcp, port: 9100, from: [172.20.20.0/22]} diff --git a/group_vars/static.yml b/group_vars/static.yml index 24c3e3a..f211563 100644 --- a/group_vars/static.yml +++ b/group_vars/static.yml @@ -2,4 +2,7 @@ firewall_in: - {proto: tcp, port: 22, from: [172.20.20.0/22]} - {proto: tcp, port: 443, from: [172.20.20.0/22]} - - {proto: tcp, port: 4949, from: [172.20.20.0/22]} + - {proto: tcp, port: 9100, from: [172.20.20.0/22]} + +sssd_allow_groups: + - root diff --git a/group_vars/vmhost.yml b/group_vars/vmhost.yml index c611eea..0b7f509 100644 --- a/group_vars/vmhost.yml +++ b/group_vars/vmhost.yml @@ -1,4 +1,4 @@ --- firewall_in: - {proto: tcp, port: 22, from: [172.20.20.0/22]} - - {proto: tcp, port: 4949, from: [172.20.20.0/22]} + - {proto: tcp, port: 9100, from: [172.20.20.0/22]} diff --git a/host_vars/audiobooks02.home.foo.sh.yml b/host_vars/audiobooks02.home.foo.sh.yml new file mode 100644 index 0000000..d6cf2c6 --- /dev/null +++ b/host_vars/audiobooks02.home.foo.sh.yml @@ -0,0 +1,6 @@ +--- +vmhost: vmhost02.home.foo.sh +network_interfaces: + - device: eth0 + vlan: 20 + mac: "52:54:00:ac:dc:48" diff --git a/host_vars/backup02.home.foo.sh.yml b/host_vars/backup02.home.foo.sh.yml index 651b34f..44d02d4 100644 --- a/host_vars/backup02.home.foo.sh.yml +++ b/host_vars/backup02.home.foo.sh.yml @@ -6,5 +6,5 @@ network_interfaces: mac: 52:54:00:ac:dc:50 datadisks: - {size: 1000} -passthrough_devices: - - "07:04.0" +virt_install_devices: + - "02:04.0" diff --git a/host_vars/dna-gw01.home.foo.sh.yml b/host_vars/dna-gw01.home.foo.sh.yml index d7c25b9..481ae6c 100644 --- a/host_vars/dna-gw01.home.foo.sh.yml +++ b/host_vars/dna-gw01.home.foo.sh.yml @@ -10,3 +10,5 @@ network_interfaces: - device: vio1 vlan: 103 proto: none +vip11_priority: 240 +vip12_priority: 120 diff --git a/host_vars/dna-gw02.home.foo.sh.yml b/host_vars/dna-gw02.home.foo.sh.yml index fae4c34..d9977c7 100644 --- a/host_vars/dna-gw02.home.foo.sh.yml +++ b/host_vars/dna-gw02.home.foo.sh.yml @@ -10,3 +10,5 @@ network_interfaces: - device: vio1 vlan: 103 proto: none +vip11_priority: 120 +vip12_priority: 240 diff --git a/host_vars/gitea-runner02.home.foo.sh.yml b/host_vars/forgejo02.home.foo.sh.yml similarity index 75% rename from host_vars/gitea-runner02.home.foo.sh.yml rename to host_vars/forgejo02.home.foo.sh.yml index 617957c..72e305b 100644 --- a/host_vars/gitea-runner02.home.foo.sh.yml +++ b/host_vars/forgejo02.home.foo.sh.yml @@ -3,4 +3,4 @@ vmhost: vmhost02.home.foo.sh network_interfaces: - device: eth0 vlan: 20 - mac: 52:54:00:ac:dc:7c + mac: 52:54:00:ac:dc:80 diff --git a/host_vars/zm02.home.foo.sh.yml b/host_vars/frigate02.home.foo.sh.yml similarity index 79% rename from host_vars/zm02.home.foo.sh.yml rename to host_vars/frigate02.home.foo.sh.yml index 340464a..1f47a47 100644 --- a/host_vars/zm02.home.foo.sh.yml +++ b/host_vars/frigate02.home.foo.sh.yml @@ -3,7 +3,7 @@ vmhost: vmhost02.home.foo.sh network_interfaces: - device: eth0 vlan: 20 - mac: "52:54:00:ac:dc:4c" + mac: "52:54:00:ac:dc:8c" nameservers: [] - device: eth1 vlan: 26 @@ -11,3 +11,5 @@ network_interfaces: netmask: 255.255.255.0 proto: static nameservers: [172.20.26.1, 172.20.26.3] +virt_install_devices: + - 004.002 diff --git a/host_vars/fsol-gw01.home.foo.sh.yml b/host_vars/fsol-gw01.home.foo.sh.yml index 798ef20..d6e9acd 100644 --- a/host_vars/fsol-gw01.home.foo.sh.yml +++ b/host_vars/fsol-gw01.home.foo.sh.yml @@ -15,6 +15,7 @@ network_interfaces: - device: vio2 vlan: 103 proto: dhcp + rdomain: 1 - device: vio3 vlan: 102 proto: none diff --git a/host_vars/fsol-gw02.home.foo.sh.yml b/host_vars/fsol-gw02.home.foo.sh.yml index 88cce43..9b00140 100644 --- a/host_vars/fsol-gw02.home.foo.sh.yml +++ b/host_vars/fsol-gw02.home.foo.sh.yml @@ -15,6 +15,7 @@ network_interfaces: - device: vio2 vlan: 103 proto: dhcp + rdomain: 1 - device: vio3 vlan: 102 proto: none diff --git a/host_vars/homeassistant01.home.foo.sh.yml b/host_vars/homeassistant01.home.foo.sh.yml index c9c1d5f..e952693 100644 --- a/host_vars/homeassistant01.home.foo.sh.yml +++ b/host_vars/homeassistant01.home.foo.sh.yml @@ -5,6 +5,10 @@ network_interfaces: vlan: 20 mac: 52:54:00:ac:dc:73 - device: eth1 + vlan: 27 + - device: eth2 vlan: 30 virt_install_devices: - - 003.002 + - 0b05:190e + - 10c4:ea60 + - /dev/ttyUSB0 diff --git a/host_vars/ldap01.home.foo.sh.yml b/host_vars/ldap01.home.foo.sh.yml index 8951d67..a64ca14 100644 --- a/host_vars/ldap01.home.foo.sh.yml +++ b/host_vars/ldap01.home.foo.sh.yml @@ -5,6 +5,6 @@ network_interfaces: vlan: 20 mac: 52:54:00:ac:dc:1f datadisks: - - {size: 10} + - {size: 10, type: nvme} ldap_master: true diff --git a/host_vars/gitea02.home.foo.sh.yml b/host_vars/mirror02.home.foo.sh.yml similarity index 75% rename from host_vars/gitea02.home.foo.sh.yml rename to host_vars/mirror02.home.foo.sh.yml index 56bb5fa..d8c639e 100644 --- a/host_vars/gitea02.home.foo.sh.yml +++ b/host_vars/mirror02.home.foo.sh.yml @@ -3,4 +3,4 @@ vmhost: vmhost02.home.foo.sh network_interfaces: - device: eth0 vlan: 20 - mac: 52:54:00:ac:dc:78 + mac: 52:54:00:ac:dc:14 diff --git a/host_vars/nms02.home.foo.sh.yml b/host_vars/nms02.home.foo.sh.yml index 4e1a686..cb1b86b 100644 --- a/host_vars/nms02.home.foo.sh.yml +++ b/host_vars/nms02.home.foo.sh.yml @@ -17,4 +17,4 @@ network_interfaces: netmask: 255.255.255.248 proto: static -vip25_priority: 0 +vip25_priority: 1 diff --git a/host_vars/oci-node01.home.foo.sh.yml b/host_vars/oci-node01.home.foo.sh.yml index 0cc5278..9116611 100644 --- a/host_vars/oci-node01.home.foo.sh.yml +++ b/host_vars/oci-node01.home.foo.sh.yml @@ -1,5 +1,7 @@ --- vmhost: vmhost01.home.foo.sh +datadisks: + - {size: 10, type: nvme} network_interfaces: - device: eth0 vlan: 20 diff --git a/host_vars/mirror01.home.foo.sh.yml b/host_vars/prometheus01.home.foo.sh.yml similarity index 74% rename from host_vars/mirror01.home.foo.sh.yml rename to host_vars/prometheus01.home.foo.sh.yml index bc25b7a..e88cf8b 100644 --- a/host_vars/mirror01.home.foo.sh.yml +++ b/host_vars/prometheus01.home.foo.sh.yml @@ -3,4 +3,4 @@ vmhost: vmhost01.home.foo.sh network_interfaces: - device: eth0 vlan: 20 - mac: 52:54:00:ac:dc:13 + mac: "52:54:00:ac:dc:83" diff --git a/host_vars/sane02.home.foo.sh.yml b/host_vars/sane02.home.foo.sh.yml new file mode 100644 index 0000000..2c0bdad --- /dev/null +++ b/host_vars/sane02.home.foo.sh.yml @@ -0,0 +1,8 @@ +--- +vmhost: vmhost02.home.foo.sh +network_interfaces: + - device: eth0 + vlan: 20 + mac: "52:54:00:ac:dc:88" +virt_install_devices: + - 001.003 diff --git a/hosts.yml b/hosts.yml index ba6f047..4c3f054 100644 --- a/hosts.yml +++ b/hosts.yml @@ -3,6 +3,9 @@ adm: hosts: adm01.home.foo.sh: adm02.home.foo.sh: +audiobooks: + hosts: + audiobooks02.home.foo.sh: backup: hosts: backup02.home.foo.sh: @@ -13,25 +16,33 @@ dnagw: hosts: dna-gw01.home.foo.sh: dna-gw02.home.foo.sh: +forgejo: + hosts: + forgejo02.home.foo.sh: + vars: + forgejo_version: "11.0.0" +frigate: + hosts: + frigate02.home.foo.sh: + vars: + frigate_version: "0.15.1" fsolgw: hosts: fsol-gw01.home.foo.sh: fsol-gw02.home.foo.sh: -gitea: - hosts: - gitea02.home.foo.sh: - vars: - gitea_version: "1.19.4" -gitearunner: - hosts: - gitea-runner02.home.foo.sh: - vars: - gitea_runner_version: "0.2.3" homeassistant: hosts: homeassistant01.home.foo.sh: vars: - homeassistant_version: "2023.7" + homeassistant_version: "2025.4" + homeassistant_integrations: + - name: electrolux_status + repo: https://github.com/albaintor/homeassistant_electrolux_status.git + version: v2.0.10 + - name: espsomfy_rts + repo: https://github.com/rstrouse/ESPSomfy-RTS-HA.git + version: v2.4.7 + nodered_version: 4.0.9 influxdb: hosts: influxdb01.home.foo.sh: @@ -45,12 +56,14 @@ log: mail: hosts: mail02.home.foo.sh: + vars: + opendkim_selector: 20250101 minecraft: hosts: minecraft01.home.foo.sh: mirror: hosts: - mirror01.home.foo.sh: + mirror02.home.foo.sh: mongodb: hosts: mongodb01.home.foo.sh: @@ -64,6 +77,8 @@ nms: hosts: nms01.home.foo.sh: nms02.home.foo.sh: + vars: + snmp_exporter_version: "0.29.0" ns: hosts: ns01.home.foo.sh: @@ -74,20 +89,34 @@ ocinode: oci-node01.home.foo.sh: oci-node02.home.foo.sh: vars: - grafana_version: "10.0.2" - rocketchat_version: "6.2.10" - roundcube_version: "1.6.1" + grafana_version: "11.6.1" + rocketchat_version: "7.5.1" + roundcube_version: "1.6.10" print: hosts: print01.home.foo.sh: +prometheus: + hosts: + prometheus01.home.foo.sh: + vars: + mysqld_exporter_version: "0.17.2" + nginx_exporter_version: "1.4.1" proxy: hosts: proxy01.home.foo.sh: proxy02.home.foo.sh: +redis: + hosts: + redis01.home.foo.sh: relay: hosts: relay01.home.foo.sh: relay02.home.foo.sh: +sane: + hosts: + sane02.home.foo.sh: + vars: + scanservjs_version: "v3.0.3" shell: hosts: shell01.foo.sh: @@ -103,23 +132,15 @@ vmhost: hosts: vmhost01.home.foo.sh: vmhost02.home.foo.sh: -zm: - hosts: - zm02.home.foo.sh: sftpbackup: children: - collab: ldap: + mongodb: sqldb: -vultr: - hosts: - atl01.vultr.foo.sh: - fedora: children: - gitearunner: openbsd: children: backup: @@ -129,27 +150,31 @@ openbsd: mqtt: ns: proxy: + redis: relay: rocky8: children: collab: +rocky9: + children: + adm: + audiobooks: + forgejo: + frigate: homeassistant: + influxdb: + ldap: mail: minecraft: + mirror: + mongodb: nas: nms: ocinode: print: + prometheus: + sane: shell: - zm: -rocky9: - children: - adm: - gitea: - influxdb: - ldap: - mirror: - mongodb: sqldb: static: vmhost: diff --git a/playbooks/adm.yml b/playbooks/adm.yml index 9833c14..3c2bd6c 100644 --- a/playbooks/adm.yml +++ b/playbooks/adm.yml @@ -18,7 +18,7 @@ name: /export src: LABEL=/export fstype: xfs - opts: noatime,noexec,nosuid,nodev + opts: noatime,nosuid,nodev passno: "0" dump: "0" state: mounted @@ -27,10 +27,15 @@ - base - ansible_host - certbot + - cups + - sshca + - ssh_known_hosts - role: keytab - principals: + keytab_principals: - "host/{{ inventory_hostname }}@{{ kerberos_realm }}" - nfs_client + - role: autofs + autofs_home: false - sssd - mkhomedir - rpm_build @@ -42,15 +47,21 @@ name: "{{ item }}" state: installed with_items: + - emacs-nox # more editors - httpd-tools # htpasswd - knot-utils # kdig (dns over tls) - libvirt-client # kvm host client - make # generic building - mariadb # mariadb client tools + - mosquitto # mqtt reading + - nano # more editors + - nmap # check for open ports - nsd # check dns zone files - podman # building containers - pylint # python linting - python3-flake8 # python linting + - speedtest-cli # testing network speed + - ShellCheck # shell script linting - virt-install # install kvm guests - wget # still in backbone for downloads - whois # read whois data @@ -63,6 +74,67 @@ Host shell??.foo.sh CheckHostIP no dest: /root/.ssh/config - mode: 0600 + mode: "0600" + owner: root + group: "{{ ansible_wheel }}" + + - name: Clone dns repo + ansible.builtin.git: + dest: /export/dns + repo: https://adm01.home.foo.sh/dns.git + update: true + version: master + environment: + GIT_SSL_CAINFO: "{{ tls_certs }}/ca.crt" + GIT_SSL_CERT: "{{ tls_certs }}/{{ inventory_hostname }}.crt" + GIT_SSL_KEY: "{{ tls_private }}/{{ inventory_hostname }}.key" + when: 'inventory_hostname != "adm01.home.foo.sh"' + - name: Link dns repo + ansible.builtin.file: + dest: /srv/dns + src: /export/dns + state: link + owner: root + group: "{{ ansible_wheel }}" + follow: false + - name: Add cron job to sync dns repo + ansible.builtin.cron: + name: sync dns repository + job: >- + GIT_SSL_CAINFO="{{ tls_certs }}/ca.crt" + GIT_SSL_CERT="{{ tls_certs }}/{{ inventory_hostname }}.crt" + GIT_SSL_KEY="{{ tls_private }}/{{ inventory_hostname }}.key" + git -C /srv/dns pull -q + minute: "02" + when: 'inventory_hostname != "adm01.home.foo.sh"' + - name: Links dns repo to web + ansible.builtin.file: + dest: "/srv/web/{{ inventory_hostname }}/dns.git" + src: /srv/dns/.git + state: link + owner: root + group: "{{ ansible_wheel }}" + + - name: Add mqtt-tail script + ansible.builtin.copy: + dest: /usr/local/bin/mqtt-tail + content: | + #!/bin/sh + set -eu + if [ -n "${1:-}" ]; then + topic="$1" + shift + else + topic="#" + fi + if [ $# -ne 0 ]; then + echo "Usage: $(basename "$0") [topic]" 1>&2 + exit 1 + fi + exec mosquitto_sub -h mqtt02.home.foo.sh -v -t "$topic" \ + --cafile "{{ tls_certs }}/ca.crt" \ + --cert "{{ tls_certs }}/{{ inventory_hostname }}.crt" \ + --key "{{ tls_private }}/{{ inventory_hostname }}.key" \ + mode: "0755" owner: root group: "{{ ansible_wheel }}" diff --git a/playbooks/audiobooks.yml b/playbooks/audiobooks.yml new file mode 100644 index 0000000..3d8ce19 --- /dev/null +++ b/playbooks/audiobooks.yml @@ -0,0 +1,25 @@ +--- +- name: Deploy KVM virtual machines + ansible.builtin.import_playbook: include/deploy-kvm-guest.yml + vars: + myhosts: audiobooks + +- name: Configure instance + hosts: audiobooks + user: root + gather_facts: true + + pre_tasks: + - name: Mount /export + ansible.posix.mount: + name: /export + src: LABEL=/export + fstype: xfs + opts: noatime,nosuid,nodev + passno: "0" + dump: "0" + state: mounted + + roles: + - base + - audiobookshelf diff --git a/playbooks/backup.yml b/playbooks/backup.yml index 3973aab..3712638 100644 --- a/playbooks/backup.yml +++ b/playbooks/backup.yml @@ -15,7 +15,7 @@ name: /export src: /dev/sd1a fstype: ffs - opts: rw,softdep,noatime + opts: rw,softdep,noatime,noexec,nosuid,nodev passno: "1" dump: "2" state: mounted @@ -25,5 +25,10 @@ roles: - base - - backup_server - - sftpbackup + - backup_base + - backup_bitbucket + - backup_github + - role: rclone + rclone_hostgroup: sftpbackup + rclone_service: backup + - rsync_backup diff --git a/playbooks/collab.yml b/playbooks/collab.yml index 6533222..89edf92 100644 --- a/playbooks/collab.yml +++ b/playbooks/collab.yml @@ -28,9 +28,9 @@ - collab - mod_auth_gssapi - role: keytab - keytab: /etc/httpd/httpd.keytab - principals: HTTP/collab.foo.sh@FOO.SH - group: apache + keytab_path: /etc/httpd/httpd.keytab + keytab_principals: HTTP/collab.foo.sh@FOO.SH + keytab_group: apache - ldap tasks: @@ -38,7 +38,7 @@ ansible.builtin.copy: content: "RedirectMatch permanent \"^/$\" /collab/\n" dest: "/etc/httpd/conf.local.d/redirects.conf" - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" notify: Restart apache @@ -61,7 +61,7 @@ dest: /srv/wikis/collab/htdocs/.htaccess owner: collab group: collab - mode: 0660 + mode: "0660" seuser: _default setype: _default diff --git a/playbooks/dna-gw.yml b/playbooks/dna-gw.yml index 00f50ea..17cb310 100644 --- a/playbooks/dna-gw.yml +++ b/playbooks/dna-gw.yml @@ -14,29 +14,14 @@ roles: - base - - ifstated - dhcpd - - nginx/server - - role: nginx/site - site: gw.home.foo.sh + - nginx + - role: nginx_site + nginx_site_name: gw.home.foo.sh - tftp - websockify tasks: - - name: Use configured dns servers and domain name - ansible.builtin.copy: - dest: /etc/dhclient.conf - content: "ignore domain-name-servers, domain-name;\n" - mode: 0644 - owner: root - group: "{{ ansible_wheel }}" - - - name: Disable resolvd - ansible.builtin.service: - name: resolvd - state: stopped - enabled: false - - name: Enable ip forwarding ansible.posix.sysctl: name: "{{ item }}" @@ -49,11 +34,49 @@ - name: Run handlers to get interfaces configured ansible.builtin.meta: flush_handlers + - name: Import ifstated role + ansible.builtin.import_role: + name: ifstated + + - name: Copy DNS private key + ansible.builtin.copy: + dest: "{{ tls_private }}/dns.home.foo.sh.key" + src: "{{ item }}" + mode: "0600" + owner: root + group: "{{ ansible_wheel }}" + with_first_found: + - /srv/letsencrypt/live/dns.home.foo.sh/privkey.pem + - "/srv/ca/private/{{ inventory_hostname }}.key" + tags: certificates + notify: Restart unbound + + - name: Copy DNS certificate and ca cert + ansible.builtin.copy: + dest: "{{ tls_certs }}/dns.home.foo.sh.crt" + src: "{{ item }}" + mode: "0644" + owner: root + group: "{{ ansible_wheel }}" + with_first_found: + - /srv/letsencrypt/live/dns.home.foo.sh/fullchain.pem + - "/srv/ca/certs/hosts/{{ inventory_hostname }}.crt" + tags: certificates + notify: Restart unbound + + - name: Import unbound role + ansible.builtin.import_role: + name: unbound + + - name: Import unbound_exporter role + ansible.builtin.import_role: + name: unbound_exporter + - name: Create tftp boot directories ansible.builtin.file: path: /srv/tftpboot/etc state: directory - mode: 0755 + mode: "0755" owner: root group: "{{ ansible_wheel }}" @@ -64,25 +87,25 @@ stty com0 115200 set tty com0 boot tftp:bsd.rd - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" - name: Create tftp pxeboot loader for OpenBSD installs ansible.builtin.get_url: - url: "https://ftp.eu.openbsd.org/pub/OpenBSD/7.3/amd64/pxeboot" - checksum: sha1:161b36d4ae3d786aa98c4836abba25f2bca8979d + url: "https://ftp.eu.openbsd.org/pub/OpenBSD/7.6/amd64/pxeboot" + checksum: sha1:c696836c1e6cc67c6c31f6ceb5daaaa4ec0632b7 dest: /srv/tftpboot/pxeboot - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" - name: Create tftp ramdisk for OpenBSD installs ansible.builtin.get_url: - url: "https://ftp.eu.openbsd.org/pub/OpenBSD//7.3/amd64/bsd.rd" - checksum: sha1:72b46ad8e97b2082d145a739264e818dcd154021 + url: "https://ftp.eu.openbsd.org/pub/OpenBSD/7.6/amd64/bsd.rd" + checksum: sha1:f690655c768ec9ef208188921ac53634a9233aca dest: /srv/tftpboot/bsd.rd - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" @@ -91,7 +114,7 @@ url: "https://boot.foo.sh/openbsd/install.conf" checksum: sha1:f6270708dad3f759df02eefeab300d9b8670f3d4 dest: /srv/tftpboot/install.conf - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" @@ -113,50 +136,7 @@ } } } - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" notify: Restart nginx - - - name: Copy DNS private key - ansible.builtin.copy: - dest: "{{ tls_private }}/dns.home.foo.sh.key" - src: "{{ item }}" - mode: 0600 - owner: root - group: "{{ ansible_wheel }}" - with_first_found: - - /srv/letsencrypt/live/dns.home.foo.sh/privkey.pem - - "/srv/ca/private/{{ inventory_hostname }}.key" - tags: certificates - notify: Restart unbound - - - name: Copy DNS certificate and ca cert - ansible.builtin.copy: - dest: "{{ tls_certs }}/dns.home.foo.sh.crt" - src: "{{ item }}" - mode: 0644 - owner: root - group: "{{ ansible_wheel }}" - with_first_found: - - /srv/letsencrypt/live/dns.home.foo.sh/fullchain.pem - - "/srv/ca/certs/hosts/{{ inventory_hostname }}.crt" - tags: certificates - notify: Restart unbound - - - name: Copy DNS zone files - ansible.builtin.copy: - dest: "/var/unbound/db/{{ item }}" - src: "/srv/dns/{{ item }}" - mode: 0644 - owner: root - group: "{{ ansible_wheel }}" - tags: dns - notify: Restart unbound - with_items: - - 20.172.in-addr.arpa - - home.foo.sh - - - name: Import unbound role - ansible.builtin.import_role: - name: unbound diff --git a/playbooks/gitea.yml b/playbooks/forgejo.yml similarity index 90% rename from playbooks/gitea.yml rename to playbooks/forgejo.yml index 72fec32..ab0ac1b 100644 --- a/playbooks/gitea.yml +++ b/playbooks/forgejo.yml @@ -2,10 +2,10 @@ - name: Deploy KVM virtual machines ansible.builtin.import_playbook: include/deploy-kvm-guest.yml vars: - myhosts: gitea + myhosts: forgejo - name: Configure instance - hosts: gitea + hosts: forgejo user: root gather_facts: true @@ -25,4 +25,4 @@ roles: - base - - gitea + - forgejo diff --git a/playbooks/zm.yml b/playbooks/frigate.yml similarity index 50% rename from playbooks/zm.yml rename to playbooks/frigate.yml index f96065c..83bc482 100644 --- a/playbooks/zm.yml +++ b/playbooks/frigate.yml @@ -2,10 +2,10 @@ - name: Deploy KVM virtual machines ansible.builtin.import_playbook: include/deploy-kvm-guest.yml vars: - myhosts: zm + myhosts: frigate - name: Configure instance - hosts: zm + hosts: frigate user: root gather_facts: true @@ -13,74 +13,54 @@ - "{{ ansible_private }}/vars.yml" pre_tasks: - - name: Mount /export + - name: Mount datadirectories ansible.posix.mount: - name: /export - src: LABEL=/export + name: "/export/frigate/{{ item }}" + src: "LABEL={{ item }}" fstype: xfs opts: noatime,noexec,nosuid,nodev passno: "0" dump: "0" state: mounted + with_items: + - config + - media roles: - base - mod_auth_gssapi - role: keytab - keytab: /etc/httpd/httpd.keytab - principals: HTTP/zm.foo.sh@FOO.SH - group: apache + keytab_path: /etc/httpd/httpd.keytab + keytab_principals: HTTP/cctv.foo.sh@FOO.SH + keytab_group: apache tasks: - - name: Run handlers to get interfaces configured - ansible.builtin.meta: flush_handlers - - # TODO: this should really be fixed - - name: Put selinux in permissive state - ansible.posix.selinux: - policy: targeted - state: permissive - - - name: Copy DNS zone files - ansible.builtin.copy: - dest: "/var/lib/unbound/{{ item }}" - src: "/srv/dns/{{ item }}" - mode: 0644 - owner: root - group: "{{ ansible_wheel }}" - tags: dns - notify: Restart unbound - with_items: - - 26.20.172.in-addr.arpa - - cam.foo.sh - - name: Include unbound role ansible.builtin.import_role: name: unbound - - name: Include dhcpd and zoneminder roles + - name: Run handlers to get interfaces configured + ansible.builtin.meta: flush_handlers + + - name: Include dhcpd role ansible.builtin.include_role: - name: "{{ item }}" - with_items: - - dhcpd - - zoneminder + name: dhcpd - - name: Install extra packages for debugging - ansible.builtin.package: - name: rtmpdump - state: installed + - name: Include frigate role + ansible.builtin.include_role: + name: frigate - - name: Require authentication for zoneminder + - name: Require authentication for frigate ansible.builtin.copy: - dest: /etc/httpd/conf.local.d/zoneminder-auth.conf + dest: /etc/httpd/conf.local.d/frigate-auth.conf content: | - + AuthType GSSAPI - GssapiBasicAuth Off + GssapiBasicAuth On AuthName "Password Required" Require valid-user - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" notify: Restart apache diff --git a/playbooks/fsol-gw.yml b/playbooks/fsol-gw.yml index 7d6efe8..639bd27 100644 --- a/playbooks/fsol-gw.yml +++ b/playbooks/fsol-gw.yml @@ -12,13 +12,6 @@ vars_files: - "{{ ansible_private }}/vars.yml" - pre_tasks: - - name: Disable resolvd service - ansible.builtin.service: - name: resolvd - state: stopped - enabled: false - tasks: - name: Enable IP forwarding ansible.posix.sysctl: @@ -30,16 +23,19 @@ - net.inet6.ip6.forwarding - name: Manually set DNS servers ansible.builtin.copy: - dest: /etc/dhclient.conf - content: "ignore domain-name-servers, domain-name;\n" - mode: 0644 + dest: /etc/dhcpleased.conf + content: | + interface vio2 { + ignore dns + } + mode: "0644" owner: root group: "{{ ansible_wheel }}" - name: Create pfsync interface ansible.builtin.copy: dest: /etc/hostname.pfsync0 content: "up syncdev vio1\n" - mode: 0600 + mode: "0600" owner: root group: "{{ ansible_wheel }}" diff --git a/playbooks/gitea-runner.yml b/playbooks/gitea-runner.yml deleted file mode 100644 index c87211c..0000000 --- a/playbooks/gitea-runner.yml +++ /dev/null @@ -1,14 +0,0 @@ ---- -- name: Deploy KVM virtual machines - ansible.builtin.import_playbook: include/deploy-kvm-guest.yml - vars: - myhosts: gitearunner - -- name: Configure instance - hosts: gitearunner - user: root - gather_facts: true - - roles: - - base - - gitea_runner diff --git a/playbooks/homeassistant.yml b/playbooks/homeassistant.yml index 965d818..1baf203 100644 --- a/playbooks/homeassistant.yml +++ b/playbooks/homeassistant.yml @@ -9,6 +9,9 @@ user: root gather_facts: true + vars_files: + - "{{ ansible_private }}/vars.yml" + pre_tasks: - name: Mount /export ansible.posix.mount: @@ -24,3 +27,4 @@ - base - ldap - homeassistant + - nodered diff --git a/playbooks/include/deploy-kvm-guest.yml b/playbooks/include/deploy-kvm-guest.yml index 4f763fd..5464cd5 100644 --- a/playbooks/include/deploy-kvm-guest.yml +++ b/playbooks/include/deploy-kvm-guest.yml @@ -9,7 +9,7 @@ char: "{{ 'bcdefghijklmnopqrstuvwxyz'|list }}" console_log: "/var/log/libvirt/qemu/{{ inventory_hostname }}.console.log" - os_disk_image: "/srv/libvirt/ssd/{{ inventory_hostname }}.a.img" + os_disk_image: "/srv/libvirt/os/{{ inventory_hostname }}.a.img" dsk_opts: bus=virtio,cache=none,device=disk,format=raw,sparse=no inject: >- @@ -75,7 +75,7 @@ echo '{{ root_pubkey }}' > /root/.ssh/authorized_keys %end dest: "{{ tmpdir.path }}/include.ks" - mode: 0600 + mode: "0600" owner: root group: "{{ ansible_wheel }}" delegate_to: "{{ vmhost }}" @@ -99,7 +99,11 @@ {% endif -%} {% if virt_install_devices is defined -%} {% for dev in virt_install_devices -%} + {% if dev | regex_search('^/dev/tty') -%} + --serial dev,path={{ dev }} + {% else -%} --hostdev {{ dev }} \ + {% endif -%} {% endfor -%} {% else -%} --controller usb,model=none \ diff --git a/playbooks/ldap.yml b/playbooks/ldap.yml index 7379a52..6c97c98 100644 --- a/playbooks/ldap.yml +++ b/playbooks/ldap.yml @@ -19,7 +19,7 @@ passno: "0" dump: "0" state: mounted - when: ldap_master is defined + when: ldap_master vars_files: - "{{ ansible_private }}/vars.yml" @@ -28,8 +28,8 @@ - base - ldap_server - role: kadmin - when: ldap_master is defined + when: ldap_master - role: ldap_netdb - when: ldap_master is defined + when: ldap_master - role: ldap_gravatar - when: ldap_master is defined + when: ldap_master diff --git a/playbooks/log.yml b/playbooks/log.yml index 13bfd5d..50caf5f 100644 --- a/playbooks/log.yml +++ b/playbooks/log.yml @@ -15,7 +15,7 @@ name: /export src: /dev/sd1a fstype: ffs - opts: rw,softdep,noatime + opts: rw,softdep,noatime,noexec,nosuid,nodev passno: "1" dump: "2" state: mounted diff --git a/playbooks/mail.yml b/playbooks/mail.yml index 072587d..c3c8041 100644 --- a/playbooks/mail.yml +++ b/playbooks/mail.yml @@ -26,18 +26,19 @@ roles: - base - role: keytab - principals: + keytab_principals: - "host/{{ inventory_hostname }}@{{ kerberos_realm }}" - "smtp/{{ mail_server }}@{{ kerberos_realm }}" - nfs_client - sssd - autofs - dovecot - - role: nginx/server - - role: nginx/site - site: "{{ mail_server }}" - redirect: https://webmail.foo.sh/ + - role: nginx + - role: nginx_site + nginx_site_name: "{{ mail_server }}" + nginx_site_redirect: https://webmail.foo.sh/ - grossd + - opendkim - spamassassin - spamassassin_clamav - spamassassin_ixhash diff --git a/playbooks/manual/check-updates.yml b/playbooks/manual/check-updates.yml new file mode 100644 index 0000000..1045eb0 --- /dev/null +++ b/playbooks/manual/check-updates.yml @@ -0,0 +1,23 @@ +--- +- hosts: all + gather_facts: true + tasks: + - name: Check updates (Linux) + ansible.builtin.command: + argv: + - dnf + - -q + - check-update + register: result + changed_when: result.rc == 100 + failed_when: result.rc not in [0, 100] + when: ansible_os_family == "RedHat" + + - name: Check updates (OpenBSD) + ansible.builtin.command: + argv: + - syspatch + - -c + register: result + changed_when: result.stdout != "" + when: ansible_os_family == "OpenBSD" diff --git a/playbooks/minecraft.yml b/playbooks/minecraft.yml index 9a88509..48b237c 100644 --- a/playbooks/minecraft.yml +++ b/playbooks/minecraft.yml @@ -15,7 +15,7 @@ name: /export src: LABEL=/export fstype: xfs - opts: noatime + opts: noatime,noexec,nosuid,nodev passno: "0" dump: "0" state: mounted diff --git a/playbooks/mirror.yml b/playbooks/mirror.yml index 7300be7..8be9d04 100644 --- a/playbooks/mirror.yml +++ b/playbooks/mirror.yml @@ -26,26 +26,30 @@ roles: - base - mirror/base - - mirror/thinlinc - - role: mirror/reportmirror - hostname: mirrors.foo.sh - mirrors: [epel, fedora] - sitename: foo.sh - password: "{{ report_mirror_pass }}" + - thinlinc_mirror + - role: reportmirror + reportmirror_hostname: mirrors.foo.sh + reportmirror_mirrors: [epel, fedora] + reportmirror_sitename: foo.sh + reportmirror_password: "{{ report_mirror_pass }}" - role: mirror/sync - label: fedora-epel - source: "rsync://rsync.nic.funet.fi/ftp/pub/mirrors/\ - fedora.redhat.com/pub/epel" - rsyncoptions: - - "--exclude=SRPMS" + mirror_label: fedora-epel + mirror_source: + "rsync://rsync.nic.funet.fi/ftp/pub/mirrors/fedora.redhat.com/pub/epel" + mirror_rsyncoptions: - "--exclude=debug" + - "--exclude=testing" + - "--exclude=aarch64" + - "--exclude=ppc64le" + - "--exclude=s390x" + - "--exclude=source" - "--delete-excluded" - postcmd: python3 /usr/local/bin/report_mirror + mirror_postcmd: python3 /usr/local/bin/report_mirror - role: mirror/sync - label: fedora - source: "rsync://rsync.nic.funet.fi/ftp/pub/mirrors/\ - fedora.redhat.com/pub/fedora/linux/" - rsyncoptions: + mirror_label: fedora + mirror_source: + "rsync://rsync.nic.funet.fi/ftp/pub/mirrors/fedora.redhat.com/pub/fedora/linux/" + mirror_rsyncoptions: - "--exclude=/atomic" - "--exclude=/development" - "--exclude=/releases/test" @@ -58,12 +62,11 @@ - "--exclude=armhfp" - "--exclude=debug" - "--delete-excluded" - postcmd: python3 /usr/local/bin/report_mirror + mirror_postcmd: python3 /usr/local/bin/report_mirror - role: mirror/sync - label: openbsd - source: "rsync://rsync.nic.funet.fi/ftp/pub/mirrors/\ - ftp.openbsd.org/pub/OpenBSD/" - rsyncoptions: + mirror_label: openbsd + mirror_source: "rsync://ftp.nluug.nl/openbsd/" + mirror_rsyncoptions: - "--include=/?.?/" - "--include=/?.?/amd64/" - "--include=/?.?/amd64/*" diff --git a/playbooks/mqtt.yml b/playbooks/mqtt.yml index 1a37f6e..8a5c0b7 100644 --- a/playbooks/mqtt.yml +++ b/playbooks/mqtt.yml @@ -9,10 +9,15 @@ user: root gather_facts: true + vars_files: + - "{{ ansible_private }}/vars.yml" + roles: - base - mosquitto + - ha_mqtt_configd - telegraf - - nginx/server - - role: nginx/site - site: iot.foo.sh + - nginx + - role: nginx_site + nginx_site_name: iot.foo.sh + - shelly_firmware diff --git a/playbooks/nas.yml b/playbooks/nas.yml index 4d451e7..22c11f2 100644 --- a/playbooks/nas.yml +++ b/playbooks/nas.yml @@ -18,7 +18,7 @@ name: /export/home src: LABEL=home fstype: xfs - opts: noatime + opts: noatime,nodev passno: "0" dump: "0" state: mounted @@ -27,7 +27,7 @@ name: /export/roles src: LABEL=roles fstype: xfs - opts: noatime + opts: noatime,nodev passno: "0" dump: "0" state: mounted @@ -38,20 +38,4 @@ - sssd - nfs_server - role: keytab - principals: "nfs/{{ inventory_hostname }}@FOO.SH" - - tasks: - - name: Copy exports file - ansible.builtin.copy: - dest: /etc/exports - content: | - /export/home 172.20.30.0/24(rw,root_squash,secure,sec=krb5p) \ - @nfsclients-rw(rw,root_squash,secure) \ - @nfsclients-ro(ro,root_squash,secure) - /export/roles 172.20.30.0/24(rw,root_squash,secure,sec=krb5p) \ - @nfsclients-rw(rw,root_squash,secure) \ - @nfsclients-ro(ro,root_squash,secure) - mode: 0644 - owner: root - group: "{{ ansible_wheel }}" - notify: Restart nfs-server + keytab_principals: "nfs/{{ inventory_hostname }}@FOO.SH" diff --git a/playbooks/nms.yml b/playbooks/nms.yml index f5ac7a0..f326b55 100644 --- a/playbooks/nms.yml +++ b/playbooks/nms.yml @@ -25,12 +25,22 @@ roles: - base - - nginx/server - - role: nginx/site - site: oob.foo.sh + - cups + - nginx + - role: nginx_site + nginx_site_name: oob.foo.sh + nginx_site_plaintext: false + - role: keytab + keytab_principals: + - "host/{{ inventory_hostname }}@{{ kerberos_realm }}" + - nfs_client + - role: autofs + autofs_home: false - sssd - mkhomedir - - tftp + - aten_pdu + - routeros + - snmp_exporter tasks: - name: Enable UDP rsyslog server @@ -45,23 +55,14 @@ vars: relay_domains: [foo.sh] - - name: Copy DNS zone files - ansible.builtin.copy: - dest: "/var/lib/unbound/{{ item }}" - src: "/srv/dns/{{ item }}" - mode: 0644 - owner: root - group: "{{ ansible_wheel }}" - tags: dns - notify: Restart unbound - with_items: - - 25.20.172.in-addr.arpa - - oob.foo.sh - - name: Import unbound role ansible.builtin.import_role: name: unbound + - name: Import dhcpd role + ansible.builtin.import_role: + name: dhcpd + # convert this to role for restart support - name: Enable NTP server for oob network ansible.builtin.lineinfile: @@ -74,10 +75,18 @@ name: "{{ item }}" state: installed with_items: - - net-snmp-utils - nmap - rcs - - scanssh - - sslscan - unzip - wget + + - name: Create sw-backup script + ansible.builtin.copy: + dest: /usr/local/bin/sw-backup + content: | + #!/bin/sh + set -eu + ssh "admin@${1}" /export > "/srv/backup/${1}.rsc" + mode: "0755" + owner: root + group: "{{ ansible_wheel }}" diff --git a/playbooks/ns.yml b/playbooks/ns.yml index 495e358..4642197 100644 --- a/playbooks/ns.yml +++ b/playbooks/ns.yml @@ -2,7 +2,7 @@ - name: Deploy KVM virtual machines ansible.builtin.import_playbook: include/deploy-kvm-guest.yml vars: - myhosts: ns:!vultr + myhosts: ns:!atl01.vultr.foo.sh - name: Configure instance hosts: ns @@ -15,9 +15,11 @@ roles: - base - nsd - - role: nginx/server - - role: nginx/site - site: "{{ nsd_server }}" - redirect: https://www.foo.sh/ + - role: nginx + - role: nginx_site + nginx_site_name: "{{ nsd_server }}" + nginx_site_redirect: https://www.foo.sh/ - role: ifstated when: "'vultr' not in group_names" + - role: blackbox_exporter + when: "inventory_hostname == 'atl01.vultr.foo.sh'" diff --git a/playbooks/oci-node.yml b/playbooks/oci-node.yml index 231a6c4..d67e62f 100644 --- a/playbooks/oci-node.yml +++ b/playbooks/oci-node.yml @@ -12,9 +12,25 @@ vars_files: - "{{ ansible_private }}/vars.yml" + pre_tasks: + - name: Mount /export + ansible.posix.mount: + name: /export + src: LABEL=/export + fstype: xfs + opts: noatime,noexec,nosuid,nodev + passno: "0" + dump: "0" + state: mounted + when: ansible_fqdn == 'oci-node01.home.foo.sh' + roles: - base - authcheck - grafana + - ipsilon - kdc - roundcube + - role: php4dvd + when: ansible_fqdn == 'oci-node01.home.foo.sh' + - rocketchat diff --git a/playbooks/print.yml b/playbooks/print.yml index d434c76..733aa88 100644 --- a/playbooks/print.yml +++ b/playbooks/print.yml @@ -14,10 +14,17 @@ roles: - base + - role: keytab + keytab_principals: + - "host/{{ inventory_hostname }}@{{ kerberos_realm }}" - sssd - mkhomedir tasks: + - name: Install unbound role + ansible.builtin.import_role: + name: unbound + - name: Run handlers to get interfaces configured ansible.builtin.meta: flush_handlers @@ -25,30 +32,20 @@ ansible.builtin.import_role: name: dhcpd - - name: Copy DNS zone files - ansible.builtin.copy: - dest: "/var/lib/unbound/{{ item }}" - src: "/srv/dns/{{ item }}" - mode: 0644 - owner: root - group: "{{ ansible_wheel }}" - tags: dns - notify: restart unbound - with_items: - - 24.20.172.in-addr.arpa - - print.foo.sh - - - name: Install unbound role - ansible.builtin.import_role: - name: unbound - - name: Install cups_server role ansible.builtin.import_role: name: cups_server - name: Install keytab for CUPS - ansible.builtin.import_role: + ansible.builtin.include_role: name: keytab vars: - keytab: /etc/cups/cups.keytab - principals: "HTTP/print.foo.sh@{{ kerberos_realm }}" + keytab_path: /etc/cups/cups.keytab + keytab_principals: "HTTP/print.foo.sh@{{ kerberos_realm }}" + + - name: Enable postfix mail relay + ansible.builtin.import_role: + name: postfix + tasks_from: relay + vars: + relay_domains: [foo.sh] diff --git a/playbooks/prometheus.yml b/playbooks/prometheus.yml new file mode 100644 index 0000000..cef9acf --- /dev/null +++ b/playbooks/prometheus.yml @@ -0,0 +1,30 @@ +--- +- name: Deploy KVM virtual machines + ansible.builtin.import_playbook: include/deploy-kvm-guest.yml + vars: + myhosts: prometheus + +- name: Configure instance + hosts: prometheus + user: root + gather_facts: true + + vars_files: + - "{{ ansible_private }}/vars.yml" + + pre_tasks: + - name: Mount /export + ansible.posix.mount: + name: /export + src: LABEL=/export + fstype: xfs + opts: noatime,noexec,nosuid,nodev + passno: "0" + dump: "0" + state: mounted + + roles: + - base + - prometheus + - mysqld_exporter + - nginx_exporter diff --git a/playbooks/proxy.yml b/playbooks/proxy.yml index e625b08..da8b9b7 100644 --- a/playbooks/proxy.yml +++ b/playbooks/proxy.yml @@ -15,90 +15,116 @@ roles: - base - ifstated - - nginx/server - - role: nginx/site - site: ca.foo.sh - - role: nginx/site - site: foo.monster - - role: nginx/site - site: tuiradc.fi - redirect: https://facebook.com/TuiraDC - - role: nginx/site - site: www.tuiradc.fi - redirect: https://facebook.com/TuiraDC - - role: nginx/site - site: foo.sh - redirect: https://www.foo.sh/ - - role: nginx/site - site: autoconfig.foo.sh - - role: nginx/site - site: boot.foo.sh - ssl_config: old - - role: nginx/site - site: bitbucket.foo.sh - redirect: https://bitbucket.org/tmakinen/ - - role: nginx/site - site: certbot.home.foo.sh - proxy: https://certbot.home.foo.sh/ - - role: nginx/site - site: chat.foo.sh - proxy: - - https://oci-node01.home.foo.sh/rocketchat/ - - https://oci-node02.home.foo.sh/rocketchat/ - - role: nginx/site - site: collab.foo.sh - proxy: https://collab01.home.foo.sh/ - - role: nginx/site - site: devel01.foo.sh - proxy: https://devel01.home.foo.sh/ - - role: nginx/site - site: dns.home.foo.sh - redirect: https://www.foo.sh/ - - role: nginx/site - site: git.foo.sh - proxy: https://gitea02.home.foo.sh/ - - role: nginx/site - site: gitea.foo.sh - redirect: https://git.foo.sh/ - - role: nginx/site - site: ha.foo.sh - proxy: https://homeassistant01.home.foo.sh/ - - role: nginx/site - site: id.foo.sh - proxy: + - nginx + - nginx_logsync + - role: nginx_site + nginx_site_name: ca.foo.sh + - role: nginx_site + nginx_site_name: foo.monster + - role: nginx_site + nginx_site_name: tuiradc.fi + nginx_site_redirect: https://facebook.com/TuiraDC + - role: nginx_site + nginx_site_name: www.tuiradc.fi + nginx_site_redirect: https://facebook.com/TuiraDC + - role: nginx_site + nginx_site_name: foo.sh + nginx_site_redirect: https://www.foo.sh/ + - role: nginx_site + nginx_site_name: apps.foo.sh + nginx_site_load_balance_method: ip_hash + nginx_site_proxy: - https://oci-node01.home.foo.sh - https://oci-node02.home.foo.sh - - role: nginx/site - site: influxdb.foo.sh - proxy: https://influxdb01.home.foo.sh/ - - role: nginx/site - site: iot.foo.sh - redirect: https://www.foo.sh/ - - role: nginx/site - site: munin.foo.sh - proxy: https://munin01.home.foo.sh/ - - role: nginx/site - site: mirrors.foo.sh - proxy: https://mirror01.home.foo.sh/ - - role: nginx/site - site: noc.foo.sh - proxy: + - role: nginx_site + nginx_site_name: audiobooks.foo.sh + nginx_site_proxy: https://audiobooks02.home.foo.sh/ + - role: nginx_site + nginx_site_name: autoconfig.foo.sh + - role: nginx_site + nginx_site_name: boot.foo.sh + - role: nginx_site + nginx_site_name: bitbucket.foo.sh + nginx_site_redirect: https://bitbucket.org/tmakinen/ + - role: nginx_site + nginx_site_name: cctv.foo.sh + nginx_site_proxy: https://frigate02.home.foo.sh/frigate/ + - role: nginx_site + nginx_site_name: certbot.home.foo.sh + nginx_site_proxy: https://certbot.home.foo.sh/ + - role: nginx_site + nginx_site_name: chat.foo.sh + nginx_site_proxy: + - https://oci-node01.home.foo.sh/rocketchat/ + - https://oci-node02.home.foo.sh/rocketchat/ + - role: nginx_site + nginx_site_name: collab.foo.sh + nginx_site_proxy: https://collab01.home.foo.sh/ + - role: nginx_site + nginx_site_name: devel01.foo.sh + nginx_site_proxy: https://devel01.home.foo.sh/ + - role: nginx_site + nginx_site_name: dns.home.foo.sh + nginx_site_redirect: https://www.foo.sh/ + - role: nginx_site + nginx_site_name: forgejo.foo.sh + nginx_site_redirect: https://git.foo.sh/ + - role: nginx_site + nginx_site_name: git.foo.sh + nginx_site_proxy: https://forgejo02.home.foo.sh/ + - role: nginx_site + nginx_site_name: gitea.foo.sh + nginx_site_redirect: https://git.foo.sh/ + - role: nginx_site + nginx_site_name: ha.foo.sh + nginx_site_proxy: https://homeassistant01.home.foo.sh/ + - role: nginx_site + nginx_site_name: id.foo.sh + nginx_site_proxy: + - https://oci-node01.home.foo.sh + - https://oci-node02.home.foo.sh + - role: nginx_site + nginx_site_name: idp.foo.sh + nginx_site_proxy: https://oci-node01.home.foo.sh/ipsilon/ + - role: nginx_site + nginx_site_name: influxdb.foo.sh + nginx_site_proxy: https://influxdb01.home.foo.sh/ + - role: nginx_site + nginx_site_name: iot.foo.sh + nginx_site_redirect: https://www.foo.sh/ + - role: nginx_site + nginx_site_name: mirrors.foo.sh + nginx_site_proxy: https://mirror02.home.foo.sh/ + - role: nginx_site + nginx_site_name: movies.foo.sh + nginx_site_proxy: + - https://oci-node01.home.foo.sh/php4dvd/ + - role: nginx_site + nginx_site_name: mta-sts.foo.sh + - role: nginx_site + nginx_site_name: noc.foo.sh + nginx_site_proxy: - https://oci-node01.home.foo.sh/grafana/ - https://oci-node02.home.foo.sh/grafana/ - - role: nginx/site - site: print.foo.sh - proxy: https://print01.home.foo.sh:631/ - - role: nginx/site - site: registry.foo.sh - proxy: ["registry01.home.foo.sh:5000", "registry02.home.foo.sh:5000"] - - role: nginx/site - site: webmail.foo.sh - proxy: + - role: nginx_site + nginx_site_name: print.foo.sh + nginx_site_proxy: https://print01.home.foo.sh:631/ + - role: nginx_site + nginx_site_name: registry.foo.sh + nginx_site_proxy: + - "registry01.home.foo.sh:5000" + - "registry02.home.foo.sh:5000" + - role: nginx_site + nginx_site_name: scan.foo.sh + nginx_site_proxy: + - https://sane02.home.foo.sh/scanservjs/ + - role: nginx_site + nginx_site_name: webmail.foo.sh + nginx_site_load_balance_method: ip_hash + nginx_site_proxy: - https://oci-node01.home.foo.sh/roundcube/ - - role: nginx/site - site: wpad.foo.sh - - role: nginx/site - site: www.foo.sh - - role: nginx/site - site: zm.foo.sh - proxy: https://zm02.home.foo.sh/ + - https://oci-node02.home.foo.sh/roundcube/ + - role: nginx_site + nginx_site_name: wpad.foo.sh + - role: nginx_site + nginx_site_name: www.foo.sh diff --git a/playbooks/relay.yml b/playbooks/relay.yml index f6cd46d..0d0e8b8 100644 --- a/playbooks/relay.yml +++ b/playbooks/relay.yml @@ -16,13 +16,13 @@ - base - ifstated - relayd - - nginx/server - - role: nginx/site - site: ldap.foo.sh - redirect: https://www.foo.sh/ - - role: nginx/site - site: ldap01.foo.sh - redirect: https://www.foo.sh/ - - role: nginx/site - site: loghost.foo.sh - redirect: https://www.foo.sh/ + - nginx + - role: nginx_site + nginx_site_name: ldap.foo.sh + nginx_site_redirect: https://www.foo.sh/ + - role: nginx_site + nginx_site_name: ldap01.foo.sh + nginx_site_redirect: https://www.foo.sh/ + - role: nginx_site + nginx_site_name: loghost.foo.sh + nginx_site_redirect: https://www.foo.sh/ diff --git a/playbooks/sane.yml b/playbooks/sane.yml new file mode 100644 index 0000000..cb8101f --- /dev/null +++ b/playbooks/sane.yml @@ -0,0 +1,39 @@ +--- +- name: Deploy KVM virtual machines + ansible.builtin.import_playbook: include/deploy-kvm-guest.yml + vars: + myhosts: sane + +- name: Configure instance + hosts: sane + user: root + gather_facts: true + + vars_files: + - "{{ ansible_private }}/vars.yml" + + roles: + - base + - sane + - scanservjs + - mod_auth_gssapi + - role: keytab + keytab_path: /etc/httpd/httpd.keytab + keytab_principals: HTTP/scan.foo.sh@FOO.SH + keytab_group: apache + + tasks: + - name: Require authentication for scanservjs + ansible.builtin.copy: + dest: /etc/httpd/conf.local.d/scanservjs-auth.conf + content: | + + AuthType GSSAPI + GssapiBasicAuth On + AuthName "Password Required" + Require valid-user + + mode: "0644" + owner: root + group: "{{ ansible_wheel }}" + notify: Restart apache diff --git a/playbooks/shell.yml b/playbooks/shell.yml index d331810..9b4b060 100644 --- a/playbooks/shell.yml +++ b/playbooks/shell.yml @@ -15,7 +15,7 @@ roles: - base - role: keytab - principals: + keytab_principals: - "host/{{ inventory_hostname }}@{{ kerberos_realm }}" - "nfs/{{ inventory_hostname }}@{{ kerberos_realm }}" - nfs_client @@ -24,9 +24,8 @@ - thinlinc_server - epel_repo - foosh_repo - - powertools_repo - - role: nginx/server - plaintext: true + - role: nginx + nginx_plaintext: true tasks: - name: Install extra package groups @@ -63,6 +62,7 @@ - pandoc - php-cli - python3-netaddr + - python3-requests - rcs - rpmlint - syslinux @@ -71,7 +71,6 @@ - tmux - whois - wireshark - - wkhtmltopdf - yamllint - zsh loop_control: @@ -98,6 +97,6 @@ content: | Host *.home.foo.sh !gw.home.foo.sh ProxyJump root@gw.home.foo.sh - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" diff --git a/playbooks/static.yml b/playbooks/static.yml index 25636a9..8471c0a 100644 --- a/playbooks/static.yml +++ b/playbooks/static.yml @@ -15,7 +15,7 @@ roles: - base - role: keytab - principals: + keytab_principals: - "host/{{ inventory_hostname }}@FOO.SH" - "nfs/{{ inventory_hostname }}@FOO.SH" - nfs_client @@ -48,7 +48,7 @@ AllowOverride AuthConfig FileInfo Indexes Limit Require all granted - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" notify: Restart apache diff --git a/playbooks/vmhost.yml b/playbooks/vmhost.yml index 66a3139..3869f1c 100644 --- a/playbooks/vmhost.yml +++ b/playbooks/vmhost.yml @@ -17,6 +17,7 @@ passno: "0" dump: "0" state: mounted + when: inventory_hostname == "vmhost02.home.foo.sh" - name: Mount /export/libvirt/nvme ansible.posix.mount: name: /export/libvirt/nvme @@ -26,10 +27,10 @@ passno: "0" dump: "0" state: mounted - - name: Mount /export/libvirt/ssd + - name: Mount /export/libvirt/os ansible.posix.mount: - name: /export/libvirt/ssd - src: LABEL=ssd + name: /export/libvirt/os + src: LABEL=os fstype: xfs opts: noatime,noexec,nosuid,nodev passno: "0" @@ -39,3 +40,4 @@ roles: - base - kvm_host + - ssh_known_hosts diff --git a/roles/ansible_host/files/urls.py.patch b/roles/ansible_host/files/urls.py.patch new file mode 100644 index 0000000..ee1dda4 --- /dev/null +++ b/roles/ansible_host/files/urls.py.patch @@ -0,0 +1,86 @@ +--- ./urls.py.orig 2024-03-27 18:55:18.077213253 +0000 ++++ urls.py 2024-03-27 18:21:07.613270952 +0000 +@@ -535,15 +535,18 @@ + UnixHTTPSConnection = None + if hasattr(httplib, 'HTTPSConnection') and hasattr(urllib_request, 'HTTPSHandler'): + class CustomHTTPSConnection(httplib.HTTPSConnection): # type: ignore[no-redef] +- def __init__(self, *args, **kwargs): ++ def __init__(self, client_cert=None, client_key=None, *args, **kwargs): + httplib.HTTPSConnection.__init__(self, *args, **kwargs) + self.context = None + if HAS_SSLCONTEXT: + self.context = self._context + elif HAS_URLLIB3_PYOPENSSLCONTEXT: + self.context = self._context = PyOpenSSLContext(PROTOCOL) +- if self.context and self.cert_file: +- self.context.load_cert_chain(self.cert_file, self.key_file) ++ ++ self._client_cert = client_cert ++ self._client_key = client_key ++ if self.context and self._client_cert: ++ self.context.load_cert_chain(self._client_cert, self._client_key) + + def connect(self): + "Connect to a host on a given (SSL) port." +@@ -564,10 +567,10 @@ + if HAS_SSLCONTEXT or HAS_URLLIB3_PYOPENSSLCONTEXT: + self.sock = self.context.wrap_socket(sock, server_hostname=server_hostname) + elif HAS_URLLIB3_SSL_WRAP_SOCKET: +- self.sock = ssl_wrap_socket(sock, keyfile=self.key_file, cert_reqs=ssl.CERT_NONE, # pylint: disable=used-before-assignment +- certfile=self.cert_file, ssl_version=PROTOCOL, server_hostname=server_hostname) ++ self.sock = ssl_wrap_socket(sock, keyfile=self._client_key, cert_reqs=ssl.CERT_NONE, # pylint: disable=used-before-assignment ++ certfile=self._client_cert, ssl_version=PROTOCOL, server_hostname=server_hostname) + else: +- self.sock = ssl.wrap_socket(sock, keyfile=self.key_file, certfile=self.cert_file, ssl_version=PROTOCOL) ++ self.sock = ssl.wrap_socket(sock, keyfile=self._client_key, certfile=self._client_cert, ssl_version=PROTOCOL) + + class CustomHTTPSHandler(urllib_request.HTTPSHandler): # type: ignore[no-redef] + +@@ -602,10 +605,6 @@ + return self.do_open(self._build_https_connection, req) + + def _build_https_connection(self, host, **kwargs): +- kwargs.update({ +- 'cert_file': self.client_cert, +- 'key_file': self.client_key, +- }) + try: + kwargs['context'] = self._context + except AttributeError: +@@ -613,7 +612,7 @@ + if self._unix_socket: + return UnixHTTPSConnection(self._unix_socket)(host, **kwargs) + if not HAS_SSLCONTEXT: +- return CustomHTTPSConnection(host, **kwargs) ++ return CustomHTTPSConnection(host, client_cert=self.client_cert, client_key=self.client_key, **kwargs) + return httplib.HTTPSConnection(host, **kwargs) + + @contextmanager +@@ -979,7 +978,7 @@ + pass + + +-def make_context(cafile=None, cadata=None, ciphers=None, validate_certs=True): ++def make_context(cafile=None, cadata=None, ciphers=None, validate_certs=True, client_cert=None, client_key=None): + if ciphers is None: + ciphers = [] + +@@ -1006,6 +1005,9 @@ + if ciphers: + context.set_ciphers(':'.join(map(to_native, ciphers))) + ++ if client_cert: ++ context.load_cert_chain(client_cert, keyfile=client_key) ++ + return context + + +@@ -1514,6 +1516,8 @@ + cadata=cadata, + ciphers=ciphers, + validate_certs=validate_certs, ++ client_cert=client_cert, ++ client_key=client_key, + ) + handlers.append(HTTPSClientAuthHandler(client_cert=client_cert, + client_key=client_key, diff --git a/roles/ansible_host/meta/main.yml b/roles/ansible_host/meta/main.yml index 27b9b1f..516a2dd 100644 --- a/roles/ansible_host/meta/main.yml +++ b/roles/ansible_host/meta/main.yml @@ -2,4 +2,4 @@ dependencies: - {role: epel_repo} - {role: git} - - {role: nginx/server} + - {role: nginx} diff --git a/roles/ansible_host/tasks/main.yml b/roles/ansible_host/tasks/main.yml index 486e145..171debe 100644 --- a/roles/ansible_host/tasks/main.yml +++ b/roles/ansible_host/tasks/main.yml @@ -7,35 +7,22 @@ - ansible - ansible-collection-ansible-posix - ansible-collection-community-general - - python3.11-dns # required for lookup('dig', 'hostname') - - python3-netaddr # required by iptables role + - patch # needed in next step + - python3.9-dns # required for lookup('dig', 'hostname') + - python3.9-ldap # required for ldap modules + - python3.9-netaddr # required by iptables role -- name: Create python3.11 lib directories - ansible.builtin.file: - path: "{{ item }}" - state: directory - mode: 0755 - owner: root - group: "{{ ansible_wheel }}" - with_items: - - /usr/local/lib/python3.11 - - /usr/local/lib/python3.11/site-packages - -- name: Kludge to add netaddr to python3.11 until package is released - ansible.builtin.copy: - dest: /usr/local/lib/python3.11/site-packages/netaddr - src: /usr/lib/python3.9/site-packages/netaddr - mode: preserve - owner: root - group: "{{ ansible_wheel }}" - remote_src: true +- name: Patch ansible to support python 3.12 clients + ansible.posix.patch: + src: urls.py.patch + dest: /usr/lib/python3.9/site-packages/ansible/module_utils/urls.py - name: Create private directory and force permissions ansible.builtin.file: path: /export/private owner: root group: root - mode: 0700 + mode: "0700" state: directory - name: Link private directory @@ -55,7 +42,7 @@ - name: Clone ansible repository ansible.builtin.git: dest: /srv/ansible - repo: https://git.foo.sh/ansible.git + repo: https://git.foo.sh/foo.sh/ansible.git update: false version: master @@ -72,7 +59,7 @@ ansible.builtin.copy: src: nginx.conf dest: /etc/nginx/conf.d/{{ inventory_hostname }}/ansible.conf - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" notify: Restart nginx @@ -83,4 +70,4 @@ src: root-bashrc.sh owner: root group: "{{ ansible_wheel }}" - mode: 0600 + mode: "0600" diff --git a/roles/apache/tasks/main.yml b/roles/apache/tasks/main.yml index 0dbdd6f..c2745ed 100644 --- a/roles/apache/tasks/main.yml +++ b/roles/apache/tasks/main.yml @@ -40,7 +40,7 @@ ansible.builtin.file: state: directory path: "{{ item }}" - mode: 0755 + mode: "0755" owner: root group: "{{ ansible_wheel }}" seuser: _default @@ -54,7 +54,7 @@ ansible.builtin.template: src: ssl.conf.j2 dest: /etc/httpd/conf.local.d/ssl.conf - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" notify: Restart apache @@ -63,7 +63,7 @@ ansible.builtin.template: src: site.conf.j2 dest: "/etc/httpd/conf.local.d/{{ inventory_hostname }}.conf" - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" notify: Restart apache diff --git a/roles/aten_pdu/files/ATEN-PE-CFG_str_1.3.128.mib b/roles/aten_pdu/files/ATEN-PE-CFG_str_1.3.128.mib new file mode 100644 index 0000000..d3f0ae6 --- /dev/null +++ b/roles/aten_pdu/files/ATEN-PE-CFG_str_1.3.128.mib @@ -0,0 +1,5065 @@ + -- MIB version: 1.3.128 + + -- MIB release note + -- | date | MIB version | note + -- -------------------------------------------------------------------------------------------------------------------------- + -- | 12/06/2021 | 1.3.128 | New dry contact sensor type: water leakage sensor + -- -------------------------------------------------------------------------------------------------------------------------- + -- | 11/25/2020 | 1.3.127 | Add new OID: communityLock and passwordLock for California passes law + -- -------------------------------------------------------------------------------------------------------------------------- + -- | 12/30/2019 | 1.3.126 | Add new OID: outletAlwaysON + -- -------------------------------------------------------------------------------------------------------------------------- + -- | 06/22/2016 | 1.3.125 | delete OID: outletRemoteAccessLock , add OID: outletLocalAccessLock & outletSequentialReboot + -- -------------------------------------------------------------------------------------------------------------------------- + -- | 04/28/2016 | 1.3.124 | Modify the string length in the description of outletName from 0~15 into 0~48 + -- -------------------------------------------------------------------------------------------------------------------------- + -- | 04/06/2016 | 1.3.123 | Modify minimum environmental humidity range from 15% into 10% + -- -------------------------------------------------------------------------------------------------------------------------- + -- | 02/22/2016 | 1.3.122 | Relocate OID: outletRemoteAccessLock + -- -------------------------------------------------------------------------------------------------------------------------- + -- | 02/03/2016 | 1.3.121 | Add new OID: outletRemoteAccessLock + -- -------------------------------------------------------------------------------------------------------------------------- + -- | 12/29/2015 | 1.1.119 | Add new OID: smtpPort + -- -------------------------------------------------------------------------------------------------------------------------- + -- | 07/31/2015 | 1.1.118 | Add new OID: popPriorityList + -- -------------------------------------------------------------------------------------------------------------------------- + -- | 07/13/2015 | 1.1.117 | Add Two dry contact & hide door sensor info + -- -------------------------------------------------------------------------------------------------------------------------- + -- | 02/11/2015 | 1.1.116 | Syntax modification of POP modes + -- -------------------------------------------------------------------------------------------------------------------------- + -- | 12/02/2014 | 1.1.115 | Wording modification + -- -------------------------------------------------------------------------------------------------------------------------- + -- | 10/22/2014 | 1.1.114 | Add get/set function for new POP feature + -- -------------------------------------------------------------------------------------------------------------------------- + -- | 07/28/2014 | 1.1.113 | Modify and unify responses of empty and not-support measurement values + -- -------------------------------------------------------------------------------------------------------------------------- + -- | 10/31/2013 | 1.1.112 | updated mib to pass smilint level 3 + -- -------------------------------------------------------------------------------------------------------------------------- + -- | 10/03/2013 | 1.1.111 | updated mib to pass smilint level 3 + -- -------------------------------------------------------------------------------------------------------------------------- + -- | 08/09/2013 | 1.1.110 | Add outlet init mode + -- -------------------------------------------------------------------------------------------------------------------------- + -- | 07/17/2013 | 1.1.109 | Add CAP Priority Settings + -- -------------------------------------------------------------------------------------------------------------------------- + -- | 07/05/2013 | 1.1.108 | Add Description and change some Syntax of oids + -- -------------------------------------------------------------------------------------------------------------------------- + -- | 05/23/2013 | 1.1.107 | Change "usrEnable" order from 40 to 47 in "UsrListEntry" + -- -------------------------------------------------------------------------------------------------------------------------- + -- | 05/21/2013 | 1.1.106 | Hide CAP function + -- -------------------------------------------------------------------------------------------------------------------------- + -- | 05/14/2013 | 1.1.105 | Modify Power Threshold Description + -- -------------------------------------------------------------------------------------------------------------------------- + -- | 05/07/2013 | 1.1.104 | Add CAP Function OID + -- -------------------------------------------------------------------------------------------------------------------------- + -- | 04/26/2013 | 1.1.103 | Add Door Sensor Type OID + -- -------------------------------------------------------------------------------------------------------------------------- + -- | 04/24/2013 | 1.1.102 | Modify Status Description of Door Sensor + -- -------------------------------------------------------------------------------------------------------------------------- + -- | 02/20/2013 | 1.1.101 | + -- -------------------------------------------------------------------------------------------------------------------------- + + -- ATEN International Co., Ltd. + -- This file defines the mib struct of Management in PE series + -- We attach this mib node on enterprises.aten.atenProducts.overip.poweroverip.pe subtree + + +ATEN-PE-CFG DEFINITIONS ::= BEGIN + + IMPORTS + enterprises, IpAddress, Gauge, TimeTicks FROM RFC1155-SMI + enterprises FROM RFC1155-SMI + DisplayString FROM RFC1213-MIB + OBJECT-TYPE FROM RFC-1212 + TRAP-TYPE FROM RFC-1215 + MODULE-IDENTITY, + NOTIFICATION-TYPE FROM SNMPv2-SMI + KeyChange FROM SNMP-USER-BASED-SM-MIB + TEXTUAL-CONVENTION FROM SNMPv2-TC; + + + + aten MODULE-IDENTITY + LAST-UPDATED "201310311110Z" + ORGANIZATION "ATEN" + CONTACT-INFO "Aten, Inc." + DESCRIPTION + "ATEN PE MIB" + REVISION "201310311110Z" + DESCRIPTION + "updated mib to pass smilint level 3" + ::= { enterprises 21317 } + + + atenProducts OBJECT IDENTIFIER ::= { aten 1 } + overip OBJECT IDENTIFIER ::= { atenProducts 3 } + poweroverip OBJECT IDENTIFIER ::= { overip 2} + pe OBJECT IDENTIFIER ::= {poweroverip 2} + userManagement OBJECT IDENTIFIER ::= { pe 1 } + control OBJECT IDENTIFIER ::= { pe 2 } + device OBJECT IDENTIFIER ::= { control 1 } + pop OBJECT IDENTIFIER ::= { device 17 } + cap OBJECT IDENTIFIER ::= { device 18 } + outlet OBJECT IDENTIFIER ::= { control 2 } + bank OBJECT IDENTIFIER ::= { control 3 } +deviceManagement OBJECT IDENTIFIER ::= { pe 3 } + config OBJECT IDENTIFIER ::= { deviceManagement 4 } + dashBoard OBJECT IDENTIFIER ::= { config 4 } + servicePorts OBJECT IDENTIFIER ::= { config 5 } + ipv4config OBJECT IDENTIFIER ::= { config 6 } + eventNotification OBJECT IDENTIFIER ::= { config 7 } + devicesnmp OBJECT IDENTIFIER ::= { eventNotification 1 } + syslog OBJECT IDENTIFIER ::= { eventNotification 2 } + smtp OBJECT IDENTIFIER ::= { eventNotification 3 } + configurationNotification OBJECT IDENTIFIER ::= { eventNotification 9 } + + + dateTime OBJECT IDENTIFIER ::= { config 8 } + timeZone OBJECT IDENTIFIER ::= { dateTime 1 } + manualInput OBJECT IDENTIFIER ::= { dateTime 2 } + networkTime OBJECT IDENTIFIER ::= { dateTime 3 } + + devicesecurity OBJECT IDENTIFIER ::= { deviceManagement 5 } + loginFailures OBJECT IDENTIFIER ::= { devicesecurity 1 } + workingMode OBJECT IDENTIFIER ::= { devicesecurity 2 } + accountPolicy OBJECT IDENTIFIER ::= { devicesecurity 3 } + loginRestriction OBJECT IDENTIFIER ::= { devicesecurity 4 } + ipFilter OBJECT IDENTIFIER ::= { loginRestriction 2 } + macFilter OBJECT IDENTIFIER ::= { loginRestriction 3 } + authentication OBJECT IDENTIFIER ::= { devicesecurity 5 } + radius OBJECT IDENTIFIER ::= { authentication 1 } +--deviceLock OBJECT IDENTIFIER ::= { pe 4 } +--CPM OBJECT IDENTIFIER ::= { pe 7 } +-- CPMDevice OBJECT IDENTIFIER ::= { CPM 9 } +-- Sensor OBJECT IDENTIFIER ::= { CPM 10 } +-- EnergySensor OBJECT IDENTIFIER ::= { CPM 11 } + + +--SNMPv3UsmAuthPrivProtocol ::= TEXTUAL-CONVENTION +-- STATUS current +-- DESCRIPTION +-- "This textual convention enumerates the authentication and privledge +-- protocol for USM configuration. +-- " +-- SYNTAX INTEGER +-- { +-- hmacMD5Auth(2), +-- hmacSHAAuth(3) +-- desPrivProtocol(5), +-- aesPrivProtocol(6) +-- } + +-- Device Control +modelName OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Indicate PE device model name." + ::= { device 1 } + +deviceName OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "The name of PE device. + string length: 1~39 + NOTE: Input string as /empty to set this object to NULL. + " + ::= { device 2 } + +deviceValueTable OBJECT-TYPE + SYNTAX SEQUENCE OF DeviceValueEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Device value table. This table displays device's current, voltage, power and + power dissipation. + " + ::= { device 3 } + +deviceValueEntry OBJECT-TYPE + SYNTAX DeviceValueEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Single deviceValue entry containing device info." + INDEX { deviceValueIndex } + ::= { deviceValueTable 1 } + +DeviceValueEntry ::= + SEQUENCE { + deviceValueIndex + INTEGER, + deviceCurrent + DisplayString, + deviceVoltage + DisplayString, + devicePower + DisplayString, + devicePowerDissipation + DisplayString, + inputMaxVoltage + INTEGER, + inputMaxCurrent + INTEGER, + powerCapacity + INTEGER, + devicePowerFactor + DisplayString + } + +deviceValueIndex OBJECT-TYPE + SYNTAX INTEGER (1) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Index of deviceValue." + ::= { deviceValueEntry 1 } +deviceCurrent OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Device electric current value. + If this measurement value is not available, it returns: N/A. + If the device does not support this OID, it returns: not-support." + ::= { deviceValueEntry 2 } +deviceVoltage OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Device voltage value. + If this measurement value is not available, it returns: N/A. + If the device does not support this OID, it returns: not-support." + ::= { deviceValueEntry 3 } +devicePower OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Device power value. + If this measurement value is not available, it returns: N/A. + If the device does not support this OID, it returns: not-support." + ::= { deviceValueEntry 4 } + +devicePowerDissipation OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Device power dissipation value. + If this measurement value is not available, it returns: N/A. + If the device does not support this OID, it returns: not-support." + ::= { deviceValueEntry 5 } + +inputMaxVoltage OBJECT-TYPE + SYNTAX INTEGER + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Device input Voltage value. unit:(V) + If the device does not support this OID, we show value 0. + " + ::= { deviceValueEntry 6 } + +inputMaxCurrent OBJECT-TYPE + SYNTAX INTEGER + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Device input Current value. unit:(A) + If the device does not support this OID, we show value 0." + ::= { deviceValueEntry 7 } + +powerCapacity OBJECT-TYPE + SYNTAX INTEGER + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Device power Capacity value.unit:(VA) + If the device does not support this OID, we show value 0." + ::= { deviceValueEntry 8 } + +devicePowerFactor OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Device power Factor value. + If the device does not support this OID, it returns: not-support." + ::= { deviceValueEntry 9 } + +sensorValueTable OBJECT-TYPE + SYNTAX SEQUENCE OF SensorValueEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Device's sensor value table. This table displays sensor's temperature, humidity and + pressure. + " + ::= { device 4 } + +sensorValueEntry OBJECT-TYPE + SYNTAX SensorValueEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Single device's sensor value entry containing device info." + INDEX { sensorValueIndex } + ::= { sensorValueTable 1 } + +SensorValueEntry ::= + SEQUENCE { + sensorValueIndex + INTEGER, + sensorTemperature + DisplayString, + sensorHumidity + DisplayString, + sensorPressure + DisplayString, + sensorProperty + INTEGER + } + +sensorValueIndex OBJECT-TYPE + SYNTAX INTEGER (1..6) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Index of sensor number." + ::= { sensorValueEntry 1 } +sensorTemperature OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Sensor's Temperature value. + If this measurement value is not available, it returns: N/A. + If the device does not support this OID, it returns: not-support." + ::= { sensorValueEntry 2 } +sensorHumidity OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Sensor's Humidity value. + If this measurement value is not available, it returns: N/A. + If the device does not support this OID, it returns: not-support." + ::= { sensorValueEntry 3 } +sensorPressure OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Sensor's Pressure value. + If this measurement value is not available, it returns: N/A. + If the device does not support this OID, it returns: not-support." + ::= { sensorValueEntry 4 } + +sensorProperty OBJECT-TYPE + SYNTAX INTEGER { intake(1), exhaust(2), floor(3) } + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Sensor's Property." + ::= { sensorValueEntry 5 } + +deviceOutletStatusTable OBJECT-TYPE + SYNTAX SEQUENCE OF DeviceOutletStatusEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Device outlet status value table." + ::= { device 5 } + +deviceOutletStatusEntry OBJECT-TYPE + SYNTAX DeviceOutletStatusEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Single deviceOutletStatus entry containing device info." + INDEX { deviceOutletStatusIndex } + ::= { deviceOutletStatusTable 1 } + +DeviceOutletStatusEntry ::= + SEQUENCE { + deviceOutletStatusIndex + INTEGER, + displayOutletStatus + INTEGER + + } + +deviceOutletStatusIndex OBJECT-TYPE + SYNTAX INTEGER (1..30) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Index of deviceOutletStatus" + ::= { deviceOutletStatusEntry 1 } +displayOutletStatus OBJECT-TYPE + SYNTAX INTEGER { off(1), on(2), pending(3), fault(4), noauth(5), not-support(6), pop(7) } + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Display outlet status." + ::= { deviceOutletStatusEntry 2 } + + +deviceConfigTable OBJECT-TYPE + SYNTAX SEQUENCE OF DeviceConfigEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Device configuration table" + ::= { device 6 } + +deviceConfigEntry OBJECT-TYPE + SYNTAX DeviceConfigEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Single deviceConfig entry containing device info." + INDEX { deviceConfigIndex } + ::= { deviceConfigTable 1 } + +DeviceConfigEntry ::= + SEQUENCE { + deviceConfigIndex + INTEGER, + deviceMinCurMT + INTEGER, + deviceMaxCurMT + INTEGER, + + deviceMinVolMT + INTEGER, + deviceMaxVolMT + INTEGER, + deviceMinPMT + INTEGER, + deviceMaxPMT + INTEGER, + + --deviceMinPDMT + --INTEGER, + deviceMaxPDMT + INTEGER + --deviceCurFlu + -- INTEGER, + --deviceVolFlu + -- INTEGER, + --devicePFlu + -- INTEGER + --devicePDFlu + --INTEGER + } + +deviceConfigIndex OBJECT-TYPE + SYNTAX INTEGER (1) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Index of deviceConfig" + ::= { deviceConfigEntry 1 } +deviceMinCurMT OBJECT-TYPE + SYNTAX INTEGER + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set device minimum electric current measurement threshold. + Example: range 0.0~32.0 represents 0~320. + NOTICE: Minimum threshold should be smaller than maximum threshold. + Empty value: -3000. + If the device does not support this OID, it returns value -2000000." + ::= { deviceConfigEntry 2 } +deviceMaxCurMT OBJECT-TYPE + SYNTAX INTEGER + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set device maximum electric current measurement threshold. + Example: range 0.0~32.0 represents 0~320 + NOTICE: Minimum threshold should be smaller than maximum threshold. + Empty value: -3000. + If the device does not support this OID, it returns value -2000000." + ::= { deviceConfigEntry 3 } + +deviceMinVolMT OBJECT-TYPE + SYNTAX INTEGER (900..2600 | -3000) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set device minimum voltage measurement threshold. + Exapmple: range 90.0~260.0 represents 900~2600 + NOTICE: Minimum threshold should be smaller than maximum threshold. + Empty value: -3000. + If the device does not support this OID, it returns value -2000000." + ::= { deviceConfigEntry 4 } + +deviceMaxVolMT OBJECT-TYPE + SYNTAX INTEGER (900..2600 | -3000) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set device maximum voltage measurement threshold. + Example: range 90.0~260.0 represents 900~2600 + NOTICE: Minimum threshold should be smaller than maximum threshold. + Empty value: -3000. + If the device does not support this OID, it returns value -2000000." + ::= { deviceConfigEntry 5 } + +deviceMinPMT OBJECT-TYPE + SYNTAX INTEGER (0..99999 | -3000) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set device minimum power measurement threshold. + Example: range 0.0 ~ 9999.9 represents 0~99999 + NOTICE: Minimum threshold should be smaller than maximum threshold. + Empty value: -3000. + If the device does not support this OID, it returns value -2000000." + ::= { deviceConfigEntry 6 } + +deviceMaxPMT OBJECT-TYPE + SYNTAX INTEGER (0..99999 | -3000) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set device maximum power measurement threshold. + Example: range 0.0 ~ 9999.9 represents 0~99999 + NOTICE: Minimum threshold should be smaller than maximum threshold. + Empty value: -3000. + If the device does not support this OID, it returns value -2000000." + ::= { deviceConfigEntry 7 } + +--deviceCurFlu OBJECT-TYPE + --SYNTAX INTEGER + --MAX-ACCESS read-write + --STATUS current + --DESCRIPTION + -- "Display device electric current fluctuation threshold. + -- Fluctuation Range = (MaxThreshold-MinThreshold)/2 x10 + -- When this value is -3000,it indicate this is NULL. + -- When set this value to -3000, indicate set this object as NULL. + -- NOTICE:Minimum threshold should be setted smaller than Maxima threshold + -- " + --::= { deviceConfigEntry 9 } + +--deviceVolFlu OBJECT-TYPE + --SYNTAX INTEGER + --MAX-ACCESS read-write + --STATUS current + --DESCRIPTION + -- "Display device voltage fluctuation threshold. + -- Fluctuation Range = (MaxThreshold-MinThreshold)/2 x10 + -- When this value is -3000,it indicate this is NULL. + -- When set this value to -3000, indicate set this object as NULL. + -- NOTICE:Minimum threshold should be setted smaller than Maxima threshold + -- " + --::= { deviceConfigEntry 10 } + +--devicePFlu OBJECT-TYPE + --SYNTAX INTEGER + --MAX-ACCESS read-write + --STATUS current + --DESCRIPTION + -- "Display device power fluctuation threshold. + -- Fluctuation Range = (MaxThreshold-MinThreshold)/2 x10 + -- When this value is -3000,it indicate this is NULL. + -- When set this value to -3000, indicate set this object as NULL. + -- NOTICE:Minimum threshold should be setted smaller than Maxima threshold + -- " + --::= { deviceConfigEntry 11 } + +--deviceMinPDMT OBJECT-TYPE + --SYNTAX INTEGER (0..2000) + --MAX-ACCESS read-write + --STATUS current + --DESCRIPTION + -- "Display or set device minimum power dissipation measurement threshold." + --::= { deviceConfigEntry 8 } +deviceMaxPDMT OBJECT-TYPE + SYNTAX INTEGER (0..999990 | -3000) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set device maximum power dissipation measurement threshold. + Example: range 0.0 ~ 99999.0 represents 0~999990 + NOTICE: Minimum threshold should be smaller than maximum threshold. + Empty value: -3000. + If the device does not support this OID, it returns value -2000000." + ::= { deviceConfigEntry 8 } +--devicePDFlu OBJECT-TYPE + --SYNTAX INTEGER (0..2000) + --MAX-ACCESS read-write + --STATUS current + --DESCRIPTION + -- "Display device power dissipation fluctuation threshold." + --::= { deviceConfigEntry 13 } + + +deviceSensorTresholdTable OBJECT-TYPE + SYNTAX SEQUENCE OF DeviceSensorTresholdEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Device environment value table" + ::= { device 7 } + +deviceSensorTresholdEntry OBJECT-TYPE + SYNTAX DeviceSensorTresholdEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Device's sensor Environment entry containing sensor info." + INDEX { deviceSensorTresholdIndex } + ::= { deviceSensorTresholdTable 1 } + +DeviceSensorTresholdEntry ::= + SEQUENCE { + deviceSensorTresholdIndex + INTEGER, + sensorMinTempMT + INTEGER, + sensorMaxTempMT + INTEGER, + + sensorMinHumMT + INTEGER, + sensorMaxHumMT + INTEGER, + sensorMinPressMT + INTEGER, + sensorMaxPressMT + INTEGER + --sensorTempFlu + --INTEGER, + --sensorHumFlu + --INTEGER, + --sensorPressFlu + --INTEGER + } + +deviceSensorTresholdIndex OBJECT-TYPE + SYNTAX INTEGER (1..6) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Index of sensor number" + ::= { deviceSensorTresholdEntry 1 } + +sensorMinTempMT OBJECT-TYPE + SYNTAX INTEGER (-200..600 | -3000) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set sensor minimum temperature measurement threshold. + Example: range -20.0 ~ 60.0 represents -200~600 + NOTICE: Minimum threshold should be smaller than maximum threshold. + Empty value: -3000. + If the device does not support this OID, it returns value -2000000." + ::= { deviceSensorTresholdEntry 2 } +sensorMaxTempMT OBJECT-TYPE + SYNTAX INTEGER (-200..600 | -3000) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set sensor maximum temperature measurement threshold. + Example: range -20.0 ~ 60.0 represents -200~600 + NOTICE: Minimum threshold should be smaller than maximum threshold. + Empty value: -3000. + If the device does not support this OID, it returns value -2000000." + ::= { deviceSensorTresholdEntry 3 } + +sensorMinHumMT OBJECT-TYPE + SYNTAX INTEGER (100..950 | -3000) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set sensor minimum humidity measurement threshold. + Example: range 10.0 ~ 95.0 represents 100~950 + NOTICE: Minimum threshold should be smaller than maximum threshold. + Empty value: -3000. + If the device does not support this OID, it returns value -2000000." + ::= { deviceSensorTresholdEntry 4 } +sensorMaxHumMT OBJECT-TYPE + SYNTAX INTEGER (100..950 | -3000) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set sensor maximum humidity measurement threshold. + Example: range 10.0 ~ 95.0 represents 100~950 + NOTICE: Minimum threshold should be smaller than maximum threshold. + Empty value: -3000. + If the device does not support this OID, it returns value -2000000." + ::= { deviceSensorTresholdEntry 5 } + +sensorMinPressMT OBJECT-TYPE + SYNTAX INTEGER (-2500..2500 | -3000) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set sensor minimum pressure measurement threshold. + Example: range -250.0 ~ 250.0 represents -2500 ~ 2500 + NOTICE: Minimum threshold should be smaller than maximum threshold. + Empty value: -3000. + If the device does not support this OID, it returns value -2000000." + ::= { deviceSensorTresholdEntry 6 } + +sensorMaxPressMT OBJECT-TYPE + SYNTAX INTEGER (-2500..2500 | -3000) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set sensor maximum pressure measurement threshold. + Example: range -250.0 ~ 250.0 represents -2500 ~ 2500 + NOTICE: Minimum threshold should be smaller than maximum threshold. + Empty value: -3000. + If the device does not support this OID, it returns value -2000000." + ::= { deviceSensorTresholdEntry 7 } + +--sensorTempFlu OBJECT-TYPE + --SYNTAX INTEGER + --MAX-ACCESS read-write + --STATUS current + --DESCRIPTION + -- "Display sensor temperature fluctuation threshold. + -- Fluctuation Range = (MaxThreshold-MinThreshold)/2 x10 + -- When this value is -3000,it indicate this is NULL. + -- When set this value to -3000, indicate set this object as NULL. + -- NOTICE:Minimum threshold should be setted smaller than Maxima threshold + -- " + --::= { deviceEnvironmentEntry 8 } + +--sensorHumFlu OBJECT-TYPE + --SYNTAX INTEGER + --MAX-ACCESS read-write + --STATUS current + --DESCRIPTION + -- "Display sensor humidity fluctuation threshold. + -- Fluctuation Range = (MaxThreshold-MinThreshold)/2 x10 + -- When this value is -3000,it indicate this is NULL. + -- When set this value to -3000, indicate set this object as NULL. + -- NOTICE:Minimum threshold should be setted smaller than Maxima threshold + -- " + --::= { deviceEnvironmentEntry 9 } + + +--sensorPressFlu OBJECT-TYPE + --SYNTAX INTEGER + --MAX-ACCESS read-write + --STATUS current + --DESCRIPTION + -- "Display sensor pressure fluctuation threshold. + -- Fluctuation Range = (MaxThreshold-MinThreshold)/2 x10 + -- When this value is -3000,it indicate this is NULL. + -- When set this value to -3000, indicate set this object as NULL. + -- NOTICE:Minimum threshold should be setted smaller than Maxima threshold + -- " + --::= { deviceEnvironmentEntry 10 } + +deviceOutletControl OBJECT-TYPE + SYNTAX INTEGER { off(1), on(2), nostatus(3), not-support(4) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + " This function is used for all outlet ports control. + Set off(1) to turn off for all outlet ports. + Set on(2) to turn on for all outlet ports. + Get this object always return nostatus(3), because there is no device status. + + " + ::= { device 8 } + +deviceOutletReboot OBJECT-TYPE + SYNTAX INTEGER { no(1), yes(2), not-support(4) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + " This function is used for all outlet ports to reboot. + Only when outlet status is ON can do outlet reboot action to all ports. + Set yes(2) to reboot all outlet ports. + Get this object always return no(1). + " + ::= { device 9 } + +switchable OBJECT-TYPE + SYNTAX INTEGER { no(1), yes(2), mix(3)} + MAX-ACCESS read-only + STATUS current + DESCRIPTION + " Outlet is switchable or not." + ::= { device 10 } + +perportreading OBJECT-TYPE + SYNTAX INTEGER { no(1), yes(2) } + MAX-ACCESS read-only + STATUS current + DESCRIPTION + " Outlet is per-port reading or not." + ::= { device 11 } + +sensornumber OBJECT-TYPE + SYNTAX INTEGER + MAX-ACCESS read-only + STATUS current + DESCRIPTION + " Sensor number." + ::= { device 12 } + +outletnumber OBJECT-TYPE + SYNTAX INTEGER + MAX-ACCESS read-only + STATUS current + DESCRIPTION + " Outlet number." + ::= { device 13 } + +banknumber OBJECT-TYPE + SYNTAX INTEGER + MAX-ACCESS read-only + STATUS current + DESCRIPTION + " Bank number." + ::= { device 14 } + +--chainnumber OBJECT-TYPE + --SYNTAX INTEGER + --MAX-ACCESS read-only + --STATUS current + --DESCRIPTION + -- " The slave device number." + --::= { device 15 } + +dryContactTable OBJECT-TYPE + SYNTAX SEQUENCE OF DryContactEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Device's Dry Contact table." + ::= { device 15 } + +dryContactEntry OBJECT-TYPE + SYNTAX DryContactEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Single device's dry contact value entry containing device info." + INDEX { dryContactIndex } + ::= { dryContactTable 1 } + +DryContactEntry ::= + SEQUENCE { + dryContactIndex + INTEGER, + dryContactStatus + INTEGER, + dryContactType + INTEGER + } + +dryContactIndex OBJECT-TYPE + SYNTAX INTEGER (1..2) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Index of dry contact number." + ::= { dryContactEntry 1 } + +dryContactStatus OBJECT-TYPE + SYNTAX INTEGER { normal(0), alert(1), not-attached(2), not-support(10) } + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Display dry contact status." + ::= { dryContactEntry 2 } + +dryContactType OBJECT-TYPE + SYNTAX INTEGER { notinstalled(0), photo(1), inductiveproximity(2), reed(3), waterleakage(4), not-support(10) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Dry contact Type Selection" + ::= { dryContactEntry 3 } + +-- +-- pop +enablePOPmode OBJECT-TYPE + SYNTAX INTEGER {no(1), yes(2)} + MAX-ACCESS read-write + STATUS current + DESCRIPTION + " Enable/Disable POP mode." + ::= { pop 1 } + +popThreshold OBJECT-TYPE + SYNTAX INTEGER + MAX-ACCESS read-write + STATUS current + DESCRIPTION + " (-1)means default value same as Bank Max Current 16 A. + + Example: range 0.0~32.0 represents 0~320 + You can define the POP threshold or set as default(-1) value." + ::= { pop 2 } + +enableOutletPOPmode OBJECT-TYPE + SYNTAX INTEGER {no(1), yes(2), not-support(3)} + MAX-ACCESS read-write + STATUS current + DESCRIPTION + " Enable/Disable Outlet POP mode." + ::= { pop 3 } + +enableLIFOPOPmode OBJECT-TYPE + SYNTAX INTEGER {no(1), yes(2), not-support(3)} + MAX-ACCESS read-write + STATUS current + DESCRIPTION + " Enable/Disable LIFO POP mode." + ::= { pop 4 } + +enablePriorityPOPmode OBJECT-TYPE + SYNTAX INTEGER {no(1), yes(2), not-support(3)} + MAX-ACCESS read-write + STATUS current + DESCRIPTION + " Enable/Disable Priority POP mode." + ::= { pop 5 } + +popPriorityList OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Indicate Outlets' power OFF priorities under Priority POP mode. + Outlet Separator ',' + Bank Separator '#' + Assign each priority in each bank by Outlet index or zero (indicate N/A) with separators in ascendant order. + e.g. for model PE8324 ( Bank1: outlet 1 ~ 16, Bank2: outlet 17 ~ 24 ) + If you want to assign priority 2, 5 of Bank 1 with Outlet 14, 3, + and priority 2, 6, 8 with of Bank 2 with Outlet 17, 23, 24 and left the rest with N/A, + please type: 0,14,0,0,3,0,0,0,0,0,0,0,0,0,0,0#0,17,0,0,0,23,0,24 + " + ::= { pop 6} + +-- CAP +enableCAPmode OBJECT-TYPE + SYNTAX INTEGER {no(1), yes(2)} + MAX-ACCESS read-write + STATUS current + DESCRIPTION + " Enable/Disable CAP mode." + ::= { cap 1 } + +outletCAPTable OBJECT-TYPE + SYNTAX SEQUENCE OF OutletCAPEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Outlet CAP table" + ::= { cap 2 } + +outletCAPEntry OBJECT-TYPE + SYNTAX OutletCAPEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Outlet CAP entry containing CAP info." + INDEX { outletCAPIndex } + ::= { outletCAPTable 1 } + +OutletCAPEntry ::= + SEQUENCE { + outletCAPIndex + INTEGER, + outletCAPPriority + INTEGER + } + +outletCAPIndex OBJECT-TYPE + SYNTAX INTEGER (1..40) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Index of outlet's CAP configuration" + ::= { outletCAPEntry 1 } + +outletCAPPriority OBJECT-TYPE + SYNTAX INTEGER (0..99) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set the CAP Priority of outlet. + Priority 0 means this outlet does not support this OID." + ::= { outletCAPEntry 2 } +-- ontlet control init mode + +outletInitMode OBJECT-TYPE + SYNTAX INTEGER {no-delaytime(1), delaytime(2), not-support(3)} + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "choose outlet init mode you want." + ::= { device 19 } + +-- outlet sequential reboot by crystal +outletSequentialReboot OBJECT-TYPE + SYNTAX INTEGER { no(1), yes(2), not-support(3) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + " This function is used to enable or disable all outlet ports to sequential reboot. + " + ::= { device 20 } + + +-- integer value + +--deviceIntegerValueTable OBJECT-TYPE +-- SYNTAX SEQUENCE OF DeviceIntegerValueEntry +-- MAX-ACCESS not-accessible +-- STATUS current +-- DESCRIPTION +-- "Device value table. This table displays device's current, voltage, power and +-- power dissipation. +-- " +-- ::= { device 99 } + +--deviceIntegerValueEntry OBJECT-TYPE +-- SYNTAX DeviceIntegerValueEntry +-- MAX-ACCESS not-accessible +-- STATUS current +-- DESCRIPTION +-- "Single deviceValue entry containing device info." +-- INDEX { deviceIntegerValueIndex } +-- ::= { deviceIntegerValueTable 1 } + +--DeviceIntegerValueEntry ::= +-- SEQUENCE { +-- deviceIntegerValueIndex +-- INTEGER, +-- deviceIntegerCurrent +-- INTEGER, +-- deviceIntegerVoltage +-- INTEGER, +-- deviceIntegerPower +-- INTEGER, +-- deviceIntegerPowerDissipation +-- INTEGER + --inputMaxVoltage + -- INTEGER, + --inputMaxCurrent + -- INTEGER, + --powerCapacity + -- INTEGER + --devicePowerFactor + -- INTEGER +-- } + +--deviceIntegerValueIndex OBJECT-TYPE +-- SYNTAX INTEGER (1) +-- MAX-ACCESS read-only +-- STATUS current +-- DESCRIPTION +-- "Index of deviceValue." +-- ::= { deviceIntegerValueEntry 1 } + +--deviceIntegerCurrent OBJECT-TYPE +-- SYNTAX INTEGER +-- MAX-ACCESS read-only +-- STATUS current +-- DESCRIPTION +-- "Device electric current value. +-- This value indicates that 1,000 times. +-- " +-- ::= { deviceIntegerValueEntry 2 } + +--deviceIntegerVoltage OBJECT-TYPE +-- SYNTAX INTEGER +-- MAX-ACCESS read-only +-- STATUS current +-- DESCRIPTION +-- "Device voltage value. +-- This value indicates that 1,000 times +-- " +-- ::= { deviceIntegerValueEntry 3 } + +--deviceIntegerPower OBJECT-TYPE +-- SYNTAX INTEGER +-- MAX-ACCESS read-only +-- STATUS current +-- DESCRIPTION +-- "Device power value. +-- This value indicates that 1,000 times. +-- " +-- ::= { deviceIntegerValueEntry 4 } + +--deviceIntegerPowerDissipation OBJECT-TYPE +-- SYNTAX INTEGER +-- MAX-ACCESS read-only +-- STATUS current +-- DESCRIPTION +-- "Device power dissipation value. +-- This value indicates that 1,000 times +-- " +-- ::= { deviceIntegerValueEntry 5 } + +--inputMaxVoltage OBJECT-TYPE +-- SYNTAX INTEGER +-- MAX-ACCESS read-only +-- STATUS current +-- DESCRIPTION +-- "Device input Voltage value. unit:(V)" +-- ::= { deviceValueEntry 6 } + +--inputMaxCurrent OBJECT-TYPE +-- SYNTAX INTEGER +-- MAX-ACCESS read-only +-- STATUS current +-- DESCRIPTION +-- "Device input Current value. unit:(A)" +-- ::= { deviceValueEntry 7 } + +--powerCapacity OBJECT-TYPE +-- SYNTAX INTEGER +-- MAX-ACCESS read-only +-- STATUS current +-- DESCRIPTION +-- "Device power Capacity value.unit:(VA)" +-- ::= { deviceValueEntry 8 } + +--devicePowerFactor OBJECT-TYPE +-- SYNTAX DisplayString +-- MAX-ACCESS read-only +-- STATUS current +-- DESCRIPTION +-- "Device power Factor value." +-- ::= { deviceValueEntry 9 } +-- + +--sensorIntegerValueTable OBJECT-TYPE +-- SYNTAX SEQUENCE OF SensorIntegerValueEntry +-- MAX-ACCESS not-accessible +-- STATUS current +-- DESCRIPTION +-- "Device's sensor value table. This table displays sensor's temperature, humidity and +-- pressure. +-- " +-- ::= { device 100 } + +--sensorIntegerValueEntry OBJECT-TYPE +-- SYNTAX SensorIntegerValueEntry +-- MAX-ACCESS not-accessible +-- STATUS current +-- DESCRIPTION +-- "Single device's sensor value entry containing device info." +-- INDEX { sensorIntegerValueIndex } +-- ::= { sensorIntegerValueTable 1 } + +--SensorIntegerValueEntry ::= +-- SEQUENCE { +-- sensorIntegerValueIndex +-- INTEGER, +-- sensorIntegerTemperature +-- INTEGER, +-- sensorIntegerHumidity +-- INTEGER, +-- sensorIntegerPressure +-- INTEGER + --sensorIntegerProperty + -- INTEGER +-- } + +--sensorIntegerValueIndex OBJECT-TYPE +-- SYNTAX INTEGER (1..6) +-- MAX-ACCESS read-only +-- STATUS current +-- DESCRIPTION +-- "Index of sensor number." +-- ::= { sensorIntegerValueEntry 1 } + +--sensorIntegerTemperature OBJECT-TYPE +-- SYNTAX INTEGER +-- MAX-ACCESS read-only +-- STATUS current +-- DESCRIPTION +-- "Sensor's Temperature value. +-- This value indicates that 1,000 times. +-- Value -300000 represents empty value." +-- ::= { sensorIntegerValueEntry 2 } + +--sensorIntegerHumidity OBJECT-TYPE +-- SYNTAX INTEGER +-- MAX-ACCESS read-only +-- STATUS current +-- DESCRIPTION +-- "Sensor's Humidity value. +-- This value indicates that 1,000 times. +-- Value -300000 represents empty value." +-- ::= { sensorIntegerValueEntry 3 } + +--sensorIntegerPressure OBJECT-TYPE +-- SYNTAX INTEGER +-- MAX-ACCESS read-only +-- STATUS current +-- DESCRIPTION +-- "Sensor's Pressure value. +-- This value indicates that 1,000 times. +-- Value -300000 represents empty value." +-- ::= { sensorIntegerValueEntry 4 } + +--sensorIntegerProperty OBJECT-TYPE +-- SYNTAX INTEGER { intake(1), exhaust(2), floor(3) } +-- MAX-ACCESS read-only +-- STATUS current +-- DESCRIPTION +-- "Sensor's Property." +-- ::= { sensorIntegerValueEntry 5 } + +-- Device Control End + +-- Outlet Control +outletValueTable OBJECT-TYPE + SYNTAX SEQUENCE OF OutletValueEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Display total outlet value table" + ::= { outlet 1 } + +outletValueEntry OBJECT-TYPE + SYNTAX OutletValueEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Single outletValue entry containing outlet info." + INDEX { outletValueIndex } + ::= { outletValueTable 1 } + +OutletValueEntry ::= + SEQUENCE { + outletValueIndex + INTEGER, + outletCurrent + DisplayString, + outletVoltage + DisplayString, + outletPower + DisplayString, + outletPowerDissipation + DisplayString, + outletMaxCurrent + INTEGER, + outletPowerFactor + DisplayString + } + +outletValueIndex OBJECT-TYPE + SYNTAX INTEGER (1..30) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Index of outlet number" + ::= { outletValueEntry 1 } +outletCurrent OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Outlet electric current value. + If this measurement value is not available, it returns: N/A. + If the device does not support this OID, it returns: not-support." + ::= { outletValueEntry 2 } +outletVoltage OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Outlet voltage value. + If this measurement value is not available, it returns: N/A. + If the device does not support this OID, it returns: not-support." + ::= { outletValueEntry 3 } +outletPower OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Outlet power value. + If this measurement value is not available, it returns: N/A. + If the device does not support this OID, it returns: not-support." + ::= { outletValueEntry 4 } +outletPowerDissipation OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Outlet power dissipation value. + If this measurement value is not available, it returns: N/A. + If the device does not support this OID, it returns: not-support." + ::= { outletValueEntry 5 } + +outletMaxCurrent OBJECT-TYPE + SYNTAX INTEGER + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Outlet Max Current value. unit: (A). + If the device does not support this OID, we show value 0. + " + ::= { outletValueEntry 6 } + +outletPowerFactor OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Outlet Power Factor value. + If the device does not support this OID, it returns: not-support." + ::= { outletValueEntry 7 } + +outlet1Status OBJECT-TYPE + SYNTAX INTEGER { off(1), on(2), pending(3), reboot(4), fault(5), noauth(6), not-support(7), pop(8)} + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display and control outlet 1 status. Can't set pending status." + ::= { outlet 2 } + +outlet2Status OBJECT-TYPE + SYNTAX INTEGER { off(1), on(2), pending(3), reboot(4), fault(5), noauth(6), not-support(7), pop(8)} + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display and control outlet 2 status. Can't set pending status." + ::= { outlet 3 } +outlet3Status OBJECT-TYPE + SYNTAX INTEGER { off(1), on(2), pending(3), reboot(4), fault(5), noauth(6), not-support(7), pop(8)} + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display and control outlet 3 status. Can't set pending status." + ::= { outlet 4 } +outlet4Status OBJECT-TYPE + SYNTAX INTEGER { off(1), on(2), pending(3), reboot(4), fault(5), noauth(6), not-support(7), pop(8)} + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display and control outlet 4 status. Can't set pending status." + ::= { outlet 5 } +outlet5Status OBJECT-TYPE + SYNTAX INTEGER { off(1), on(2), pending(3), reboot(4), fault(5), noauth(6), not-support(7), pop(8)} + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display and control outlet 5 status. Can't set pending status." + ::= { outlet 6 } +outlet6Status OBJECT-TYPE + SYNTAX INTEGER { off(1), on(2), pending(3), reboot(4), fault(5), noauth(6), not-support(7), pop(8)} + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display and control outlet 6 status. Can't set pending status." + ::= { outlet 7 } +outlet7Status OBJECT-TYPE + SYNTAX INTEGER { off(1), on(2), pending(3), reboot(4), fault(5), noauth(6), not-support(7), pop(8)} + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display and control outlet 7 status. Can't set pending status." + ::= { outlet 8 } +outlet8Status OBJECT-TYPE + SYNTAX INTEGER { off(1), on(2), pending(3), reboot(4), fault(5), noauth(6), not-support(7), pop(8)} + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display and control outlet 8 status. Can't set pending status." + ::= { outlet 9 } + +outlet9Status OBJECT-TYPE + SYNTAX INTEGER { off(1), on(2), pending(3), reboot(4), fault(5), noauth(6), not-support(7), pop(8)} + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display and control outlet 9 status. Can't set pending status." + ::= { outlet 11 } + +outlet10Status OBJECT-TYPE + SYNTAX INTEGER { off(1), on(2), pending(3), reboot(4), fault(5), noauth(6), not-support(7), pop(8)} + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display and control outlet 10 status. Can't set pending status." + ::= { outlet 12 } + +outlet11Status OBJECT-TYPE + SYNTAX INTEGER { off(1), on(2), pending(3), reboot(4), fault(5), noauth(6), not-support(7), pop(8)} + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display and control outlet 11 status. Can't set pending status." + ::= { outlet 13 } + +outlet12Status OBJECT-TYPE + SYNTAX INTEGER { off(1), on(2), pending(3), reboot(4), fault(5), noauth(6), not-support(7), pop(8)} + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display and control outlet 12 status. Can't set pending status." + ::= { outlet 14 } + +outlet13Status OBJECT-TYPE + SYNTAX INTEGER { off(1), on(2), pending(3), reboot(4), fault(5), noauth(6), not-support(7), pop(8)} + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display and control outlet 13 status. Can't set pending status." + ::= { outlet 15 } + +outlet14Status OBJECT-TYPE + SYNTAX INTEGER { off(1), on(2), pending(3), reboot(4), fault(5), noauth(6), not-support(7), pop(8)} + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display and control outlet 14 status. Can't set pending status." + ::= { outlet 16 } + +outlet15Status OBJECT-TYPE + SYNTAX INTEGER { off(1), on(2), pending(3), reboot(4), fault(5), noauth(6), not-support(7), pop(8)} + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display and control outlet 15 status. Can't set pending status." + ::= { outlet 17 } + +outlet16Status OBJECT-TYPE + SYNTAX INTEGER { off(1), on(2), pending(3), reboot(4), fault(5), noauth(6), not-support(7), pop(8)} + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display and control outlet 16 status. Can't set pending status." + ::= { outlet 18 } + +outlet17Status OBJECT-TYPE + SYNTAX INTEGER { off(1), on(2), pending(3), reboot(4), fault(5), noauth(6), not-support(7), pop(8)} + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display and control outlet 17 status. Can't set pending status." + ::= { outlet 19 } + +outlet18Status OBJECT-TYPE + SYNTAX INTEGER { off(1), on(2), pending(3), reboot(4), fault(5), noauth(6), not-support(7), pop(8)} + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display and control outlet 18 status. Can't set pending status." + ::= { outlet 20 } + +outlet19Status OBJECT-TYPE + SYNTAX INTEGER { off(1), on(2), pending(3), reboot(4), fault(5), noauth(6), not-support(7), pop(8)} + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display and control outlet 19 status. Can't set pending status." + ::= { outlet 21 } + +outlet20Status OBJECT-TYPE + SYNTAX INTEGER { off(1), on(2), pending(3), reboot(4), fault(5), noauth(6), not-support(7), pop(8)} + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display and control outlet 20 status. Can't set pending status." + ::= { outlet 22 } + +outlet21Status OBJECT-TYPE + SYNTAX INTEGER { off(1), on(2), pending(3), reboot(4), fault(5), noauth(6), not-support(7), pop(8)} + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display and control outlet 21 status. Can't set pending status." + ::= { outlet 23 } + +outlet22Status OBJECT-TYPE + SYNTAX INTEGER { off(1), on(2), pending(3), reboot(4), fault(5), noauth(6), not-support(7), pop(8)} + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display and control outlet 22 status. Can't set pending status." + ::= { outlet 24 } + +outlet23Status OBJECT-TYPE + SYNTAX INTEGER { off(1), on(2), pending(3), reboot(4), fault(5), noauth(6), not-support(7), pop(8)} + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display and control outlet 23 status. Can't set pending status." + ::= { outlet 25 } + +outlet24Status OBJECT-TYPE + SYNTAX INTEGER { off(1), on(2), pending(3), reboot(4), fault(5), noauth(6), not-support(7), pop(8)} + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display and control outlet 24 status. Can't set pending status." + ::= { outlet 26 } + +outlet25Status OBJECT-TYPE + SYNTAX INTEGER { off(1), on(2), pending(3), reboot(4), fault(5), noauth(6), not-support(7), pop(8)} + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display and control outlet 25 status. Can't set pending status." + ::= { outlet 27 } + +outlet26Status OBJECT-TYPE + SYNTAX INTEGER { off(1), on(2), pending(3), reboot(4), fault(5), noauth(6), not-support(7), pop(8)} + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display and control outlet 26 status. Can't set pending status." + ::= { outlet 28 } + +outlet27Status OBJECT-TYPE + SYNTAX INTEGER { off(1), on(2), pending(3), reboot(4), fault(5), noauth(6), not-support(7), pop(8)} + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display and control outlet 27 status. Can't set pending status." + ::= { outlet 29 } + +outlet28Status OBJECT-TYPE + SYNTAX INTEGER { off(1), on(2), pending(3), reboot(4), fault(5), noauth(6), not-support(7), pop(8)} + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display and control outlet 28 status. Can't set pending status." + ::= { outlet 30 } + +outlet29Status OBJECT-TYPE + SYNTAX INTEGER { off(1), on(2), pending(3), reboot(4), fault(5), noauth(6), not-support(7), pop(8)} + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display and control outlet 29 status. Can't set pending status." + ::= { outlet 31 } + +outlet30Status OBJECT-TYPE + SYNTAX INTEGER { off(1), on(2), pending(3), reboot(4), fault(5), noauth(6), not-support(7), pop(8)} + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display and control outlet 30 status. Can't set pending status." + ::= { outlet 32 } + +outlet31Status OBJECT-TYPE + SYNTAX INTEGER { off(1), on(2), pending(3), reboot(4), fault(5), noauth(6), not-support(7), pop(8)} + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display and control outlet 31 status. Can't set pending status." + ::= { outlet 33 } + +outlet32Status OBJECT-TYPE + SYNTAX INTEGER { off(1), on(2), pending(3), reboot(4), fault(5), noauth(6), not-support(7), pop(8)} + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display and control outlet 32 status. Can't set pending status." + ::= { outlet 34 } + +outlet33Status OBJECT-TYPE + SYNTAX INTEGER { off(1), on(2), pending(3), reboot(4), fault(5), noauth(6), not-support(7), pop(8)} + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display and control outlet 33 status. Can't set pending status." + ::= { outlet 35 } + + +outlet34Status OBJECT-TYPE + SYNTAX INTEGER { off(1), on(2), pending(3), reboot(4), fault(5), noauth(6), not-support(7), pop(8)} + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display and control outlet 34 status. Can't set pending status." + ::= { outlet 36 } + +outlet35Status OBJECT-TYPE + SYNTAX INTEGER { off(1), on(2), pending(3), reboot(4), fault(5), noauth(6), not-support(7), pop(8)} + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display and control outlet 35 status. Can't set pending status." + ::= { outlet 37 } + +outlet36Status OBJECT-TYPE + SYNTAX INTEGER { off(1), on(2), pending(3), reboot(4), fault(5), noauth(6), not-support(7), pop(8)} + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display and control outlet 36 status. Can't set pending status." + ::= { outlet 38 } + +outlet37Status OBJECT-TYPE + SYNTAX INTEGER { off(1), on(2), pending(3), reboot(4), fault(5), noauth(6), not-support(7), pop(8)} + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display and control outlet 37 status. Can't set pending status." + ::= { outlet 39 } + +outlet38Status OBJECT-TYPE + SYNTAX INTEGER { off(1), on(2), pending(3), reboot(4), fault(5), noauth(6), not-support(7), pop(8)} + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display and control outlet 38 status. Can't set pending status." + ::= { outlet 40 } + +outlet39Status OBJECT-TYPE + SYNTAX INTEGER { off(1), on(2), pending(3), reboot(4), fault(5), noauth(6), not-support(7), pop(8)} + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display and control outlet 39 status. Can't set pending status." + ::= { outlet 41 } + +outlet40Status OBJECT-TYPE + SYNTAX INTEGER { off(1), on(2), pending(3), reboot(4), fault(5), noauth(6), not-support(7), pop(8)} + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display and control outlet 40 status. Can't set pending status." + ::= { outlet 42 } + +outlet41Status OBJECT-TYPE + SYNTAX INTEGER { off(1), on(2), pending(3), reboot(4), fault(5), noauth(6), not-support(7), pop(8)} + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display and control outlet 41 status. Can't set pending status." + ::= { outlet 43 } + +outlet42Status OBJECT-TYPE + SYNTAX INTEGER { off(1), on(2), pending(3), reboot(4), fault(5), noauth(6), not-support(7), pop(8)} + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display and control outlet 42 status. Can't set pending status." + ::= { outlet 44 } + +-- + +outletSwitchableTable OBJECT-TYPE + SYNTAX SEQUENCE OF OutletSwitchableEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + " + " + ::= { outlet 70 } + +outletSwitchableEntry OBJECT-TYPE + SYNTAX OutletSwitchableEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "" + INDEX { outletSwitchableIndex } + ::= { outletSwitchableTable 1 } + + OutletSwitchableEntry ::= + SEQUENCE { + outletSwitchableIndex + INTEGER, + outletSwitchable + INTEGER + + } + +outletSwitchableIndex OBJECT-TYPE + SYNTAX INTEGER (1..30) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Index of outlet number. + " + ::= { outletSwitchableEntry 1 } + +outletSwitchable OBJECT-TYPE + SYNTAX INTEGER {no(1), yes(2) } + MAX-ACCESS read-only + STATUS current + DESCRIPTION + " + " + ::= { outletSwitchableEntry 2 } + + +--outlet integer value + +--outletIntegerValueTable OBJECT-TYPE +-- SYNTAX SEQUENCE OF OutletIntegerValueEntry +-- MAX-ACCESS not-accessible +-- STATUS current +-- DESCRIPTION +-- "Display total outlet value table" +-- ::= { outlet 99 } + +--outletIntegerValueEntry OBJECT-TYPE +-- SYNTAX OutletIntegerValueEntry +-- MAX-ACCESS not-accessible +-- STATUS current +-- DESCRIPTION +-- "Single outletValue entry containing outlet info." +-- INDEX { outletIntegerValueIndex } +-- ::= { outletIntegerValueTable 1 } + +--OutletIntegerValueEntry ::= +-- SEQUENCE { +-- outletIntegerValueIndex +-- INTEGER, +-- outletIntegerCurrent +-- INTEGER, +-- outletIntegerVoltage +-- INTEGER, +-- outletIntegerPower +-- INTEGER, +-- outletIntegerPowerDissipation +-- INTEGER +-- } + +--outletIntegerValueIndex OBJECT-TYPE +-- SYNTAX INTEGER (1..30) +-- MAX-ACCESS read-only +-- STATUS current +-- DESCRIPTION +-- "Index of outlet number. +-- " +-- ::= { outletIntegerValueEntry 1 } + +--outletIntegerCurrent OBJECT-TYPE +-- SYNTAX INTEGER +-- MAX-ACCESS read-only +-- STATUS current +-- DESCRIPTION +-- "Outlet electric current value. +-- This value indicates that 1,000 times. +-- " +-- ::= { outletIntegerValueEntry 2 } + +--outletIntegerVoltage OBJECT-TYPE +-- SYNTAX INTEGER +-- MAX-ACCESS read-only +-- STATUS current +-- DESCRIPTION +-- "Outlet voltage value. +-- This value indicates that 1,000 times. +-- " +-- ::= { outletIntegerValueEntry 3 } + +--outletIntegerPower OBJECT-TYPE +-- SYNTAX INTEGER +-- MAX-ACCESS read-only +-- STATUS current +-- DESCRIPTION +-- "Outlet power value. +-- This value indicates that 1,000 times." +-- ::= { outletIntegerValueEntry 4 } + +--outletIntegerPowerDissipation OBJECT-TYPE +-- SYNTAX INTEGER +-- MAX-ACCESS read-only +-- STATUS current +-- DESCRIPTION +-- "Outlet power dissipation value. +-- This value indicates that 1,000 times." +-- ::= { outletIntegerValueEntry 5 } + + + + + +outletConfigTable OBJECT-TYPE + SYNTAX SEQUENCE OF OutletConfigEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Outlet configuration table" + ::= { outlet 10 } + +outletConfigEntry OBJECT-TYPE + SYNTAX OutletConfigEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Outlet Config entry containing outlet info." + INDEX { outletConfigIndex } + ::= { outletConfigTable 1 } + +OutletConfigEntry ::= + SEQUENCE { + outletConfigIndex + INTEGER, + outletName + DisplayString, + outletConfirmation + INTEGER, + outletOnDelayTime + INTEGER, + outletOffDelayTime + INTEGER, + outletShutdownMethod + INTEGER, + outletMAC + DisplayString, + outletMinCurMT + INTEGER, + outletMaxCurMT + INTEGER, + outletMinVolMT + INTEGER, + outletMaxVolMT + INTEGER, + outletMinPMT + INTEGER, + outletMaxPMT + INTEGER, + outletMaxPDMT + INTEGER, + outletLocalAccessLock + INTEGER +-- outletAlwaysON +-- INTEGER + } + +outletConfigIndex OBJECT-TYPE + SYNTAX INTEGER (1..30) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Index of outlet number" + ::= { outletConfigEntry 1 } +outletName OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set the name of outlet. + If the device does not support this OID, we show n/a. + string length: 0~48 + NOTE: Input string as /empty to set this object to NULL. + " + ::= { outletConfigEntry 2 } +outletConfirmation OBJECT-TYPE + SYNTAX INTEGER { no(1), yes(2) , noauth(3), not-support(4)} + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set the confirmation of outlet." + ::= { outletConfigEntry 3 } +outletOnDelayTime OBJECT-TYPE + SYNTAX INTEGER (0..999 | -1) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set the ON delay time of outlet. + When this model does not support the OID, we show value -1. " + ::= { outletConfigEntry 4 } +outletOffDelayTime OBJECT-TYPE + SYNTAX INTEGER (0..999 | -1) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set the OFF delay time of outlet. + When this model does not support the OID, we show value -1. " + ::= { outletConfigEntry 5 } +outletShutdownMethod OBJECT-TYPE + SYNTAX INTEGER { kill-the-power(1), wake-on-lan(2), after-ac-back(3), not-support(4)} + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set the shutdown mehtod of outlet." + ::= { outletConfigEntry 6 } +outletMAC OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set the MAC address of ShutdownMethod. + If the device does not support this OID, we show n/a. + string length: 12 + " + ::= { outletConfigEntry 7 } +outletMinCurMT OBJECT-TYPE + SYNTAX INTEGER + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set the outlet minimum electric current measurment threshold. + Example: range 0.0 ~16.0 rerpresnts 0~160 + NOTICE: Minimum threshold should be smaller than maximum threshold. + Empty value: -3000. + If the device does not support this OID, it returns value -2000000." + ::= { outletConfigEntry 8 } +outletMaxCurMT OBJECT-TYPE + SYNTAX INTEGER + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set the outlet maximum electric current measurment threshold. + Example: range 0.0 ~16.0 represents 0~160 + NOTICE: Minimum threshold should be smaller than maximum threshold. + Empty value: -3000. + If the device does not support this OID, it returns value -2000000." + ::= { outletConfigEntry 9 } + +outletMinVolMT OBJECT-TYPE + SYNTAX INTEGER (900..2600 | -3000 | -2000000) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set the outlet minimum voltage measurment threshold. + Example: range 90.0 ~260.0 represents 900~2600 + NOTICE: Minimum threshold should be smaller than maximum threshold. + Empty value: -3000. + If the device does not support this OID, it returns value -2000000." + ::= { outletConfigEntry 10 } +outletMaxVolMT OBJECT-TYPE + SYNTAX INTEGER (900..2600 | -3000 | -2000000) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set the outlet maximum voltage measurment threshold. + Example: range 90.0 ~260.0 represents 900~2600 + NOTICE: Minimum threshold should be smaller than maximum threshold. + Empty value: -3000. + If the device does not support this OID, it returns value -2000000." + ::= { outletConfigEntry 11 } + +outletMinPMT OBJECT-TYPE + SYNTAX INTEGER (0..99999 | -3000 | -2000000) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set the outlet minimum power measurment threshold. + Example: range 0.0 ~ 9999.9 represents 0~99999 + NOTICE: Minimum threshold should be smaller than maximum threshold. + Empty value: -3000. + If the device does not support this OID, it returns value -2000000." + ::= { outletConfigEntry 12 } +outletMaxPMT OBJECT-TYPE + SYNTAX INTEGER (0..99999 | -3000 | -2000000) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set the outlet maximum power measurment threshold. + Example: range 0.0 ~ 9999.9 represents 0~99999 + NOTICE: Minimum threshold should be smaller than maximum threshold. + Empty value: -3000. + If the device does not support this OID, it returns value -2000000." + ::= { outletConfigEntry 13 } + +outletMaxPDMT OBJECT-TYPE + SYNTAX INTEGER (0..999990 | -3000 | -2000000) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set the outlet maximum power dissipation measurment threshold. + Example: range 0.0 ~ 99999.0 represents 0~999990 + NOTICE: Minimum threshold should be smaller than maximum threshold. + Empty value: -3000. + If the device does not support this OID, it returns value -2000000." + ::= { outletConfigEntry 14 } + +outletLocalAccessLock OBJECT-TYPE + SYNTAX INTEGER {unlocked(1), locked(2), not-support(3)} + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Whether local access of Outlet is locked by remote or not." + ::= { outletConfigEntry 15} + +--outletAlwaysON OBJECT-TYPE +-- SYNTAX INTEGER {no(1), yes(2), not-support(3)} +-- MAX-ACCESS read-write +-- STATUS current +-- DESCRIPTION +-- "Whether the outlet is always ON or not." +-- ::= { outletConfigEntry 16 } + +-- Outlet Control End +-- Bank control +breakerStatusTable OBJECT-TYPE + SYNTAX SEQUENCE OF BreakerStatusEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Display total bank value table" + ::= { bank 1 } + +breakerStatusEntry OBJECT-TYPE + SYNTAX BreakerStatusEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Single bankValue entry containing bank info." + INDEX { breakerStatusIndex } + ::= { breakerStatusTable 1 } + +BreakerStatusEntry ::= + SEQUENCE { + breakerStatusIndex + INTEGER, + breakerStatus + INTEGER + } + +breakerStatusIndex OBJECT-TYPE + SYNTAX INTEGER (1..30) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Index of breaker number." + ::= { breakerStatusEntry 1 } + +breakerStatus OBJECT-TYPE + SYNTAX INTEGER { off(1), on(2), not-support(3)} + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Breaker status." + ::= { breakerStatusEntry 2 } + + +bankValueTable OBJECT-TYPE + SYNTAX SEQUENCE OF BankValueEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Display total bank value table" + ::= { bank 2 } + +bankValueEntry OBJECT-TYPE + SYNTAX BankValueEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Single bankValue entry containing bank info." + INDEX { bankValueIndex } + ::= { bankValueTable 1 } + +BankValueEntry ::= + SEQUENCE { + bankValueIndex + INTEGER, + bankCurrent + DisplayString, + bankVoltage + DisplayString, + bankPower + DisplayString, + bankPowerDissipation + DisplayString, + bankMaxCurrent + INTEGER, + bankAttachStatus + INTEGER, + bankPowerFactor + DisplayString + } + +bankValueIndex OBJECT-TYPE + SYNTAX INTEGER (1..30) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Index of bank number" + ::= { bankValueEntry 1 } +bankCurrent OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Bank electric current value. + If this measurement value is not available, it returns: N/A. + If the device does not support this OID, it returns: not-support." + ::= { bankValueEntry 2 } +bankVoltage OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Bank voltage value. + We put this OID to write access type for user to set the reference voltage on EC1000 model. + And the setting should be the numbers. You can set 0 to clear the setting. + If this measurement value is not available, it returns: N/A. + If the device does not support this OID, it returns: not-support." + ::= { bankValueEntry 3 } + +bankPower OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Bank power value. + If this measurement value is not available, it returns: N/A. + If the device does not support this OID, it returns: not-support." + ::= { bankValueEntry 4 } + +bankPowerDissipation OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Bank power dissipation value. + If this measurement value is not available, it returns: N/A. + If the device does not support this OID, it returns: not-support." + ::= { bankValueEntry 5 } + + +bankMaxCurrent OBJECT-TYPE + SYNTAX INTEGER + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The Bank Max Current value. unit: (A) + EC1000:0A~320A + " + ::= { bankValueEntry 6 } + +bankAttachStatus OBJECT-TYPE + SYNTAX INTEGER { noattached(1), attached(2), error(3), noexisted(4) } + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The status of Energy sensor Bank attached status." + ::= { bankValueEntry 7 } + +bankPowerFactor OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Bank Power Factor value. + If the device does not support this OID, it returns: not-support." + ::= { bankValueEntry 8 } + +bankConfigTable OBJECT-TYPE + SYNTAX SEQUENCE OF BankConfigEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Bank configuration table" + ::= { bank 3 } + +bankConfigEntry OBJECT-TYPE + SYNTAX BankConfigEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Bank Config entry containing Bank info." + INDEX { bankConfigIndex } + ::= { bankConfigTable 1 } + +BankConfigEntry ::= + SEQUENCE { + bankConfigIndex + INTEGER, + bankName + DisplayString, + bankMinCurMT + INTEGER, + bankMaxCurMT + INTEGER, + + bankMinVolMT + INTEGER, + bankMaxVolMT + INTEGER, + + bankMinPMT + INTEGER, + bankMaxPMT + INTEGER, + --outletMinPDMT + --INTEGER, + bankMaxPDMT + INTEGER + --outletCurFlu + --INTEGER, + --outletVolFlu + --INTEGER, + --outletPFlu + --INTEGER + --outletPDFlu + --INTEGER + } + +bankConfigIndex OBJECT-TYPE + SYNTAX INTEGER (1..30) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Index of bank number" + ::= { bankConfigEntry 1 } + +bankName OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set the name of bank. + When this model does not support the OID, we show n/a. + string length: 0~15 + NOTE: Input string as /empty to set this object to NULL. + " + ::= { bankConfigEntry 2 } + + +bankMinCurMT OBJECT-TYPE + SYNTAX INTEGER + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set the outlet minimum electric current measurment threshold. + Example: range 0.0 ~16.0 rerpresnts 0~160 + NOTICE: Minimum threshold should be smaller than maximum threshold. + Empty value: -3000. + If the device does not support this OID, it returns value -2000000." + ::= { bankConfigEntry 3 } + +bankMaxCurMT OBJECT-TYPE + SYNTAX INTEGER + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set the outlet maximum electric current measurment threshold. + Example: range 0.0 ~16.0 represents 0~160 + NOTICE: Minimum threshold should be smaller than maximum threshold. + Empty value: -3000. + If the device does not support this OID, it returns value -2000000." + ::= { bankConfigEntry 4} + +bankMinVolMT OBJECT-TYPE + SYNTAX INTEGER (900..2600 | -3000 | -2000000) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set the outlet minimum voltage measurment threshold. + Example: range 90.0 ~260.0 represents 900~2600 + NOTICE: Minimum threshold should be smaller than maximum threshold. + Empty value: -3000. + If the device does not support this OID, it returns value -2000000." + ::= { bankConfigEntry 5 } +bankMaxVolMT OBJECT-TYPE + SYNTAX INTEGER (900..2600 | -3000 | -2000000) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set the outlet maximum voltage measurment threshold. + Example: range 90.0 ~260.0 represents 900~2600 + NOTICE: Minimum threshold should be smaller than maximum threshold. + Empty value: -3000. + If the device does not support this OID, it returns value -2000000." + ::= { bankConfigEntry 6 } + +bankMinPMT OBJECT-TYPE + SYNTAX INTEGER (0..99999| -3000 | -2000000) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set the outlet minimum power measurment threshold. + Example: range 0.0 ~ 9999.9 represents 0~99999 + NOTICE: Minimum threshold should be smaller than maximum threshold. + Empty value: -3000. + If the device does not support this OID, it returns value -2000000." + ::= { bankConfigEntry 7 } +bankMaxPMT OBJECT-TYPE + SYNTAX INTEGER (0..99999 | -3000 | -2000000) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set the outlet maximum power measurment threshold. + Example: range 0.0 ~ 9999.9 represents 0~99999 + NOTICE: Minimum threshold should be smaller than maximum threshold. + Empty value: -3000. + If the device does not support this OID, it returns value -2000000." + ::= { bankConfigEntry 8 } + +--outletMinPDMT OBJECT-TYPE + --SYNTAX INTEGER (0..100) + --MAX-ACCESS read-write + --STATUS current + --DESCRIPTION + -- "Display or set the outlet minimum power dissipation measurment threshold ." + --::= { outletConfigEntry 14 } + +bankMaxPDMT OBJECT-TYPE + SYNTAX INTEGER (0..999990 | -3000 | -2000000) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set the outlet maximum power dissipation measurment threshold. + Example: range 0.0 ~ 99999.0 represents 0~999990 + NOTICE: Minimum threshold should be smaller than maximum threshold. + Empty value: -3000. + If the device does not support this OID, it returns value -2000000." + ::= { bankConfigEntry 9 } + + +bankControlTable OBJECT-TYPE + SYNTAX SEQUENCE OF BankControlEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Bank Control table" + ::= { bank 4 } + +bankControlEntry OBJECT-TYPE + SYNTAX BankControlEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Bank control entry." + INDEX { bankControlIndex } + ::= { bankControlTable 1 } + +BankControlEntry ::= + SEQUENCE { + bankControlIndex + INTEGER, + bankControlStatus + INTEGER + } + +bankControlIndex OBJECT-TYPE + SYNTAX INTEGER (1..4) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Index of bank number" + ::= { bankControlEntry 1 } + +bankControlStatus OBJECT-TYPE + SYNTAX INTEGER {off(1), on(2), reboot(3), nostatus(4), not-support(5)} + MAX-ACCESS read-write + STATUS current + DESCRIPTION + " This function is used for outlet control of bank. + Set off(1) to turn off for outlet control of bank. + Set on(2) to turn on for all outlet control of bank. + Set reboot(3) to turn on for outlet control of bank. + Get this object always return nostatus(3), because there is no bank status. + " + ::= { bankControlEntry 2 } + +-- Bank control End + + +--bankIntegerValueTable OBJECT-TYPE +-- SYNTAX SEQUENCE OF BankIntegerValueEntry +-- MAX-ACCESS not-accessible +-- STATUS current +-- DESCRIPTION +-- "Display total bank value table" +-- ::= { bank 99 } + +--bankIntegerValueEntry OBJECT-TYPE +-- SYNTAX BankIntegerValueEntry +-- MAX-ACCESS not-accessible +-- STATUS current +-- DESCRIPTION +-- "Single bankValue entry containing bank info." +-- INDEX { bankIntegerValueIndex } +-- ::= { bankIntegerValueTable 1 } + +--BankIntegerValueEntry ::= +-- SEQUENCE { +-- bankIntegerValueIndex +-- INTEGER, +-- bankIntegerCurrent +-- INTEGER, +-- bankIntegerVoltage +-- INTEGER, +-- bankIntegerPower +-- INTEGER, +-- bankIntegerPowerDissipation +-- INTEGER + --bankIntegerMaxCurrent + -- INTEGER, + --bankIntegerAttachStatus + -- INTEGER, + --bankIntegerPowerFactor + --INTEGER +-- } + +--bankIntegerValueIndex OBJECT-TYPE +-- SYNTAX INTEGER (1..30) +-- MAX-ACCESS read-only +-- STATUS current +-- DESCRIPTION +-- "Index of bank number. +-- " +-- ::= { bankIntegerValueEntry 1 } + +--bankIntegerCurrent OBJECT-TYPE +-- SYNTAX INTEGER +-- MAX-ACCESS read-only +-- STATUS current +-- DESCRIPTION +-- "Bank electric current value. +-- This value indicates that 1,000 times." +-- ::= { bankIntegerValueEntry 2 } +--bankIntegerVoltage OBJECT-TYPE +-- SYNTAX INTEGER +-- MAX-ACCESS read-only +-- STATUS current +-- DESCRIPTION +-- "Bank voltage value. +-- This value indicates that 1,000 times." +-- ::= { bankIntegerValueEntry 3 } + +--bankIntegerPower OBJECT-TYPE +-- SYNTAX INTEGER +-- MAX-ACCESS read-only +-- STATUS current +-- DESCRIPTION +-- "Bank power value. +-- This value indicates that 1,000 times." +-- ::= { bankIntegerValueEntry 4 } + +--bankIntegerPowerDissipation OBJECT-TYPE +-- SYNTAX INTEGER +-- MAX-ACCESS read-only +-- STATUS current +-- DESCRIPTION +-- "Bank power dissipation value. +-- This value indicates that 1,000 times." +-- ::= { bankIntegerValueEntry 5 } + + +--bankMaxCurrent OBJECT-TYPE +-- SYNTAX INTEGER +-- MAX-ACCESS read-only +-- STATUS current +-- DESCRIPTION +-- "The Bank Max Current value. unit: (A) +-- EC1000:0A~320A +-- " +-- ::= { bankValueEntry 6 } + +--bankAttachStatus OBJECT-TYPE +-- SYNTAX INTEGER { noattached(1), attached(2), error(3) } +-- MAX-ACCESS read-only +-- STATUS current +-- DESCRIPTION +-- "The status of Energy sensor Bank attached status." +-- ::= { bankValueEntry 7 } + +--bankPowerFactor OBJECT-TYPE +-- SYNTAX DisplayString +-- MAX-ACCESS read-only +-- STATUS current +-- DESCRIPTION +-- "Bank Power Factor value" +-- ::= { bankValueEntry 8 } + + + +-- Device Management +deviceMAC OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Display device MAC address." + ::= { config 1 } + +deviceIPv4 OBJECT-TYPE + SYNTAX IpAddress + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Display device IP address." + ::= { config 2 } + +deviceFWversion OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Display device FW version." + ::= { config 3 } + +-- dashboard settings +dashboardRow OBJECT-TYPE + SYNTAX INTEGER (1..26) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set device's dashboard row number." + ::= { dashBoard 1 } + +dashboardColumn OBJECT-TYPE + SYNTAX INTEGER (1..26) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set device's dashboard column number." + ::= { dashBoard 2 } + +dashboardRackName OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set device's dashboard rack name. + string length: 1~32 + NOTE: Input string as /empty to set this object to NULL. + " + ::= { dashBoard 3 } + +httpPort OBJECT-TYPE + SYNTAX INTEGER (1..65535) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set the HTTP port of PE device." + ::= { servicePorts 1 } + +httpsPort OBJECT-TYPE + SYNTAX INTEGER (1..65535) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set the HTTPs port of PE device." + ::= { servicePorts 2 } + +httpsOnlyEnable OBJECT-TYPE + SYNTAX INTEGER {yes(1), no(2) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Enable to use Webpage HTTPs only or disable to use Webpage HTTP/HTTPs" + ::= { servicePorts 3 } + + + +staticIPEnabled OBJECT-TYPE + SYNTAX INTEGER { no(1), yes(2) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set IPv4 address automatically or not" + ::= { ipv4config 1 } +fixedIPv4 OBJECT-TYPE + SYNTAX IpAddress + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set fixed IPv4 address" + ::= { ipv4config 2 } +subnetMask OBJECT-TYPE + SYNTAX IpAddress + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set subnet mask address" + ::= { ipv4config 3 } +gateway OBJECT-TYPE + SYNTAX IpAddress + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set gateway address" + ::= { ipv4config 4 } +staticDNSEnabled OBJECT-TYPE + SYNTAX INTEGER { no(1), yes(2) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set DNS address automatically or not" + ::= { ipv4config 5 } +dnsPreferIPv4 OBJECT-TYPE + SYNTAX IpAddress + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set prefer DNS address" + ::= { ipv4config 6 } +dnsAlternateIPv4 OBJECT-TYPE + SYNTAX IpAddress + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set alternate DNS address" + ::= { ipv4config 7 } + +trapEnabled OBJECT-TYPE + SYNTAX INTEGER { no(1), yes(2) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Indicates if this trap entry is enabled or not. + You should set the username/auth-password/priv-password first, when choosing snmpv3. + You should set the community string first, when choosing snmpv1/v2c." + ::= { devicesnmp 1 } + +trapVersion OBJECT-TYPE + SYNTAX INTEGER { v1(1), v2c(2), v3(3)} + MAX-ACCESS read-write + STATUS current + DESCRIPTION + " Choose SNMP Trap version to send trap. + You should set the username/auth-password/priv-password first, when choosing snmpv3. + You should set the community string first, when choosing snmpv1/v2c." + ::= { devicesnmp 2 } + +snmpTrapTable OBJECT-TYPE + SYNTAX SEQUENCE OF SnmpTrapEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "PE SNMP agent trap setup table. If users want to use trap, + they must set enable trap, ip and community first." + ::= { devicesnmp 3 } + +snmpTrapEntry OBJECT-TYPE + SYNTAX SnmpTrapEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Single trap entry containing trap receiver info." + INDEX { trapReceiverNumber } + ::= { snmpTrapTable 1 } + +SnmpTrapEntry ::= + SEQUENCE { + trapReceiverNumber + INTEGER, + --trapEnabled + --INTEGER, + trapReceiverIPAddress + IpAddress, + --trapCommunity + --DisplayString, + trapPort + INTEGER, + trapCommunity + DisplayString, + trapUsername + DisplayString, + trapAuthpassword + DisplayString, + trapPrivpassword + DisplayString + } + +trapReceiverNumber OBJECT-TYPE + SYNTAX INTEGER (1..2) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Index of trap receiver" + ::= { snmpTrapEntry 1 } + + + +trapReceiverIPAddress OBJECT-TYPE + SYNTAX IpAddress + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Trap receiver IP address" + ::= { snmpTrapEntry 2 } + + +trapPort OBJECT-TYPE + SYNTAX INTEGER (1..65535) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "NMS trap port to be used by agent to send trap" + ::= { snmpTrapEntry 3 } + +trapCommunity OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..20)) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "If use SNMPv1/v2c to receive trap should set this Community string. + MAX string length: 20 + NOTE: Input string as /empty to set this object to NULL. + " + ::= { snmpTrapEntry 4 } +trapUsername OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..20)) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "If use SNMPv3 to receive trap should set this string. + NOTE: Input string as /empty to set this object to NULL. + MAX string length: 20 + " + ::= { snmpTrapEntry 5 } +trapAuthpassword OBJECT-TYPE + SYNTAX DisplayString (SIZE (8..20)) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "If use SNMPv3 to receive trap should set this string. + MAX string length: 20 + NOTE: Input string as /empty to set this object to NULL. + " + ::= { snmpTrapEntry 6 } +trapPrivpassword OBJECT-TYPE + SYNTAX DisplayString (SIZE (8..20)) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "If use SNMPv3 to receive trap should set this string. + MAX string length: 20 + NOTE: Input string as /empty to set this object to NULL. + " + ::= { snmpTrapEntry 7 } + + +--privacypassword OBJECT-TYPE +-- SYNTAX DisplayString +-- MAX-ACCESS read-write +-- STATUS current +-- DESCRIPTION +-- "SNMPv3 privacy password to be used by agent to send trap +-- string length: 8~20 +-- " +-- ::= { devicesnmp 4 } + +--engineID OBJECT-TYPE +-- SYNTAX DisplayString +-- MAX-ACCESS read-only +-- STATUS current +-- DESCRIPTION +-- "EngineID" +-- ::= { devicesnmp 5 } +--engineBoot OBJECT-TYPE +-- SYNTAX INTEGER +-- MAX-ACCESS read-only +-- STATUS current +-- DESCRIPTION +-- "EngineBoot" +-- ::= { devicesnmp 6 } +--engineTime OBJECT-TYPE +-- SYNTAX INTEGER +-- MAX-ACCESS read-only +-- STATUS current +-- DESCRIPTION +-- "EngineTime" +-- ::= { devicesnmp 7 } +--engineMaxMSG OBJECT-TYPE +-- SYNTAX INTEGER +-- MAX-ACCESS read-only +-- STATUS current +-- DESCRIPTION +-- "EngineMaxMSG" +-- ::= { devicesnmp 8 } +sysLogServerEnabled OBJECT-TYPE + SYNTAX INTEGER { no(1), yes(2) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set syslog server address automatically or not" + ::= { syslog 1 } +sysLogServerIPv4 OBJECT-TYPE + SYNTAX IpAddress + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set syslog server address" + ::= { syslog 2 } +sysLogServerPort OBJECT-TYPE + SYNTAX INTEGER (1..65535) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set syslog server port" + ::= { syslog 3 } + +smtpServerEnabled OBJECT-TYPE + SYNTAX INTEGER { no(1), yes(2) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set SMTP server enable status." + ::= { smtp 1 } +smtpServerName OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set a SMTP server name. + NOTE: Input string as /empty to set this object to NULL. + " + ::= { smtp 2 } +smtpAuthEnabled OBJECT-TYPE + SYNTAX INTEGER { no(1), yes(2) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set authentication of SMTP server." + ::= { smtp 3 } +smtpAccountName OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set a user's name of SMTP server. + NOTE: Input string as /empty to set this object to NULL. + " + ::= { smtp 4 } +smtpAccountPwd OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set a user's password of SMTP server. + NOTE: Input string as /empty to set this object to NULL. + " + ::= { smtp 5 } +smtpMailFrom OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set a mail of SMTP server. + NOTE: Input string as /empty to set this object to NULL. + " + ::= { smtp 6 } +smtpMailTo OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set a mail of SMTP server. + NOTE: Input string as /empty to set this object to NULL. + " + ::= { smtp 7 } +smtpPort OBJECT-TYPE + SYNTAX INTEGER (1..65535) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set SMTP server port" + ::= { smtp 8 } + +-- + +configurationNotifyEnabled OBJECT-TYPE + SYNTAX INTEGER { no(1), yes(2) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + " " + ::= { configurationNotification 1 } + +configurationNotifyTrapMSG NOTIFICATION-TYPE + STATUS current + --OBJECTS { customTrapMSG } + DESCRIPTION " " + ::= { configurationNotification 2 } + + +-- +timeZoneSetting OBJECT-TYPE + SYNTAX INTEGER + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set the time zone of PE device. + (0) [GMT-12:00] Eniwetok Kwajalein + (1) [GMT-11:00] Midway Island Samoa + (2) [GMT-10:00] Hawaii + (3) [GMT-09:00] Alaska + (4) [GMT-08:00] Pacific Time (US & Canada); Tijuana + (5) [GMT-07:00] Mountain Time (US & Canada) + (6) [GMT-07:00] Arizona + (7) [GMT-06:00] Central Time (US & Canada) + (8) [GMT-06:00] Mexico City + (9) [GMT-06:00] Saskatchewan + (10)[GMT-06:00] Central America + (11)[GMT-05:00] Eastern Time (US & Canada) + (12)[GMT-05:00] Indiana (East) + (13)[GMT-05:00] Bogota Lima Quito + (14)[GMT-04:00] Atlantic Time (Canada) + (15)[GMT-04:00] Caracas La Paz + (16)[GMT-04:00] Santiago + (17)[GMT-03:30] Newfoundland + (18)[GMT-03:00] Buenos Aires Georgetown + (19)[GMT-03:00] Brasilia + (20)[GMT-03:00] Greenland + (21)[GMT-02:00] Mid-Atlantic + (22)[GMT-01:00] Azores + (23)[GMT-01:00] Cape Verde Is + (24)[GMT] Casablanca Monrovia + (25)[GMT] Greenwich Mean Time: Dublin Edinburgh Lisbon London + (26)[GMT+01:00] Amsterdam Copenhagen Madrid Paris Vilnius + (27)[GMT+01:00] West Central Africa + (28)[GMT+01:00] Belgrade Sarajevo Skopje Sofija Zagreb + (29)[GMT+01:00] Bratislava Budapest Ljubljana Prague Warsaw + (30)[GMT+01:00] Brussels Berlin Bern Rome Stockholm Vienna + (31)[GMT+02:00] Cairo + (32)[GMT+02:00] Harare Pretoria + (33)[GMT+02:00] Jerusalem + (34)[GMT+02:00] Bucharest + (35)[GMT+02:00] Helsinki Riga Tallinn + (36)[GMT+02:00] Athens Istanbul Minsk + (37)[GMT+03:00] Kuwait Riyadh + (38)[GMT+03:00] Nairobi + (39)[GMT+03:00] Baghdad + (40)[GMT+03:00] Moscow St. Petersburg Volgograd + (41)[GMT+03:30] Tehran + (42)[GMT+04:00] Abu Dhabi Muscat + (43)[GMT+04:00] Baku Tbilisi Yerevan + (44)[GMT+04:30] Kabul + (45)[GMT+05:00] Islamabad Karachi Tashkent + (46)[GMT+05:00] Ekaterinburg + (47)[GMT+05:30] Calcutta Chennai Mumbai New Delhi + (48)[GMT+05:45] Kathmandu + (49)[GMT+06:00] Astana Dhaka + (50)[GMT+06:00] Sri Jayawardenepura + (51)[GMT+06:00] Almaty Novosibirsk + (52)[GMT+06:30] Rangoon + (53)[GMT+07:00] Bangkok Hanoi Jakarta + (54)[GMT+07:00] Krasnoyarsk + (55)[GMT+08:00] Beijing Chongqing Hong Kong Urumqi + (56)[GMT+08:00] Perth + (57)[GMT+08:00] Kuala Lumpur Singapore + (58)[GMT+08:00] Taipei + (59)[GMT+08:00] Irkutsk Ulaan Bataar + (60)[GMT+09:00] Osaka Sapporo Tokyo + (61)[GMT+09:00] Seoul + (62)[GMT+09:00] Yakutsk + (63)[GMT+09:30] Darwin + (64)[GMT+09:30] Adelaide + (65)[GMT+10:00] Canberra Melbourne Sydney + (66)[GMT+10:00] Brisbane + (67)[GMT+10:00] Guam Port Moresby + (68)[GMT+10:00] Hobart + (69)[GMT+10:00] Vladivostok + (70)[GMT+11:00] Magadan Solomon Is New Caledonia + (71)[GMT+12:00] Fiji Kamchatka Marshall Is. + (72)[GMT+12:00] Auckland Wellington + (73)[GMT+13:00] Nuku'alofa + " + ::= { timeZone 1 } + +dstEnabled OBJECT-TYPE + SYNTAX INTEGER { no(1), yes(2) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set daylight savings time ." + ::= { timeZone 2 } + +dateSetting OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set date in a manual way.(This is Greenwich Mean Time, GMT) + string length: 10 + This value format must match the following form: + YYYY-MM-DD + ex. 2011-01-01 + Note: range of year: 2000-2099 + range of month: 01-12 + range of day: 01-31 + " + ::= { manualInput 1 } + +timeSetting OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set time in a manual way.(This is Greenwich Mean Time, GMT) + string length: 8 + This value format must match the following form: + HH:MM:SS + ex. 02:02:02 + Note: range of hour: 00-24 + range of minute: 00-60 + range of second: 00-60 + + " + ::= { manualInput 2 } + +--syncWithPC OBJECT-TYPE +-- SYNTAX INTEGER { no(1), yes(2) } +-- MAX-ACCESS read-write +-- STATUS current +-- DESCRIPTION +-- "Display or set date time useing sync PC way." +-- ::= { manualInput 3 } + +autoAdjustEnabled OBJECT-TYPE + SYNTAX INTEGER { no(1), yes(2) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set date time useing auto adjustment way." + ::= { networkTime 1 } + +preferNTP OBJECT-TYPE + SYNTAX INTEGER + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set prefer NTP server. + AU | ntp1.cs.mu.OZ.AU(0), + AU | ntp0.cs.mu.OZ.AU(1), + BE | ntp2.oma.be(2), + BE | ntp1.oma.be(3), + BR | ntps1.pads.ufrj.br(4), + CH | swisstime.ethz.ch(5), + CL | ntp.shoa.cl(6), + CZ | ntp.nic.cz(7), + DE | ntp.stairweb.de(8), + DE | ntps1-0.cs.tu-berlin.de(9), + DE | ptbtime1.ptb.de(10), + DE | ntp1.fau.de(11), + DE | ptbtime2.ptb.de(12), + DE | time1.one4vision.de(13), + DE | rustime01.rus.uni-stuttgart.de(14), + DE | ntp.probe-networks.de(15), + DE | ntp2.fau.de(16), + ES | hora.roa.es(17), + HK | stdtime.gov.hk(18), + IE | ntp-galway.hea.net(19), + IT | ntp1.inrim.it(20), + IT | ntp2.inrim.it(21), + JP | clock.tl.fukuoka-u.ac.jp(22), + JP | ntp.nict.jp(23), + JP | clock.nc.fukuoka-u.ac.jp(24), + KR | ntp.xbsd.kr(25), + MX | cronos.cenam.mx(26), + NL | ntp0.nl.uu.net(27), + NL | ntp1.nl.uu.net(28), + NL | ntp.remco.org(29), + NL | ntp0.nl.net(30), + PL | vega.cbk.poznan.pl(31), + PL | ntp.ntp-servers.com(32), + RO | ntp3.usv.ro(33), + RO | ntp2.usv.ro(34), + RU | ntp1.vniiftri.ru; ntp1.imvp.ru(35), + RU | ntp2.vniiftri.ru; ntp2.imvp.ru(36), + SE | ntp1.mmo.netnod.se(37), + SE | ntp1.sth.netnod.se(38), + SE | ntp2.mmo.netnod.se(39), + SE | ntp2.sth.netnod.se(40), + SE | time2.stupi.se(41), + SE | ntp1.sp.se(42), + SE | timehost.lysator.liu.se(43), + SI | ntp.mostovna.com(44), + US CA | timekeeper.isi.edu(45), + US CA | clock.sjc.he.net(46), + US CA | nist1.symmetricom.com(47), + US CA | clock.via.net(48), + US CA | nist1.aol-ca.truetime.com(49), + US CA | clock.isc.org(50), + US CA | clepsydra.dec.com(51), + US CA | gps.layer42.net(52), + US CA | time.no-such-agency.net(53), + US CA | nist1-sj.WiTime.net(54), + US CA | clock.fmt.he.net(55), + US CO | time-b.timefreq.bldrdoc.gov(56), + US CO | time-a.timefreq.bldrdoc.gov(57), + US CO | utcnist.colorado.edu(58), + US CO | time-c.timefreq.bldrdoc.gov(59), + US DE | rackety.udel.edu(60), + US DE | mizbeaver.udel.edu(61), + US GA | nist1.columbiacountyga.gov(62), + US IL | ntp.your.org(63), + US MA | bonehed.lcs.mit.edu(64), + US MA | time.keneli.org(65), + US MA | ntp0.broad.mit.edu(66), + US MD | time-a.nist.gov(67), + US MD | time-b.nist.gov(68), + US MI | nist.netservicesgroup.com(69), + US NY | nist1-ny.WiTime.net(70), + US NY | clock.nyc.he.net(71), + US UT | time.xmission.com(72), + US VA | nist1-dc.WiTime.net(73), + US VA | nist1.aol-va.truetime.com(74), + US WA | time-nw.nist.gov(75), + FR | utp.univ-lyon1.fr(76), + FR | ntp-sop.inria.fr(77), + FR | ntp.tuxfamily.net(78), + UK | bear.zoo.bt.co.uk(79) + " + ::= { networkTime 2 } + +preferServerIPenable OBJECT-TYPE + SYNTAX INTEGER { no(1), yes(2) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Enable or disable prefer custom server IP." + ::= { networkTime 3 } + +preferNTPIp OBJECT-TYPE + SYNTAX IpAddress + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set prefer NTP server IP." + ::= { networkTime 4 } + +alternateNtpEnabled OBJECT-TYPE + SYNTAX INTEGER { no(1), yes(2) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set date time using alternate NTP server." + ::= { networkTime 5 } + +alternateNtp OBJECT-TYPE + SYNTAX INTEGER + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set alternative NTP server. + AU | ntp1.cs.mu.OZ.AU(0), + AU | ntp0.cs.mu.OZ.AU(1), + BE | ntp2.oma.be(2), + BE | ntp1.oma.be(3), + BR | ntps1.pads.ufrj.br(4), + CH | swisstime.ethz.ch(5), + CL | ntp.shoa.cl(6), + CZ | ntp.nic.cz(7), + DE | ntp.stairweb.de(8), + DE | ntps1-0.cs.tu-berlin.de(9), + DE | ptbtime1.ptb.de(10), + DE | ntp1.fau.de(11), + DE | ptbtime2.ptb.de(12), + DE | time1.one4vision.de(13), + DE | rustime01.rus.uni-stuttgart.de(14), + DE | ntp.probe-networks.de(15), + DE | ntp2.fau.de(16), + ES | hora.roa.es(17), + HK | stdtime.gov.hk(18), + IE | ntp-galway.hea.net(19), + IT | ntp1.inrim.it(20), + IT | ntp2.inrim.it(21), + JP | clock.tl.fukuoka-u.ac.jp(22), + JP | ntp.nict.jp(23), + JP | clock.nc.fukuoka-u.ac.jp(24), + KR | ntp.xbsd.kr(25), + MX | cronos.cenam.mx(26), + NL | ntp0.nl.uu.net(27), + NL | ntp1.nl.uu.net(28), + NL | ntp.remco.org(29), + NL | ntp0.nl.net(30), + PL | vega.cbk.poznan.pl(31), + PL | ntp.ntp-servers.com(32), + RO | ntp3.usv.ro(33), + RO | ntp2.usv.ro(34), + RU | ntp1.vniiftri.ru; ntp1.imvp.ru(35), + RU | ntp2.vniiftri.ru; ntp2.imvp.ru(36), + SE | ntp1.mmo.netnod.se(37), + SE | ntp1.sth.netnod.se(38), + SE | ntp2.mmo.netnod.se(39), + SE | ntp2.sth.netnod.se(40), + SE | time2.stupi.se(41), + SE | ntp1.sp.se(42), + SE | timehost.lysator.liu.se(43), + SI | ntp.mostovna.com(44), + US CA | timekeeper.isi.edu(45), + US CA | clock.sjc.he.net(46), + US CA | nist1.symmetricom.com(47), + US CA | clock.via.net(48), + US CA | nist1.aol-ca.truetime.com(49), + US CA | clock.isc.org(50), + US CA | clepsydra.dec.com(51), + US CA | gps.layer42.net(52), + US CA | time.no-such-agency.net(53), + US CA | nist1-sj.WiTime.net(54), + US CA | clock.fmt.he.net(55), + US CO | time-b.timefreq.bldrdoc.gov(56), + US CO | time-a.timefreq.bldrdoc.gov(57), + US CO | utcnist.colorado.edu(58), + US CO | time-c.timefreq.bldrdoc.gov(59), + US DE | rackety.udel.edu(60), + US DE | mizbeaver.udel.edu(61), + US GA | nist1.columbiacountyga.gov(62), + US IL | ntp.your.org(63), + US MA | bonehed.lcs.mit.edu(64), + US MA | time.keneli.org(65), + US MA | ntp0.broad.mit.edu(66), + US MD | time-a.nist.gov(67), + US MD | time-b.nist.gov(68), + US MI | nist.netservicesgroup.com(69), + US NY | nist1-ny.WiTime.net(70), + US NY | clock.nyc.he.net(71), + US UT | time.xmission.com(72), + US VA | nist1-dc.WiTime.net(73), + US VA | nist1.aol-va.truetime.com(74), + US WA | time-nw.nist.gov(75), + FR | utp.univ-lyon1.fr(76), + FR | ntp-sop.inria.fr(77), + FR | ntp.tuxfamily.net(78), + UK | bear.zoo.bt.co.uk(79) + " + ::= { networkTime 6 } + +alternateServerIPenable OBJECT-TYPE + SYNTAX INTEGER { no(1), yes(2) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Enable or disable alternate custom server IP." + ::= { networkTime 7 } + +alternateNtpIp OBJECT-TYPE + SYNTAX IpAddress + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set alternative NTP server IP." + ::= { networkTime 8 } + +adjustTimeEveryDays OBJECT-TYPE + SYNTAX INTEGER + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set frequency of adjustment in days." + ::= { networkTime 9 } + +--adjustTimeNow OBJECT-TYPE + --SYNTAX INTEGER { no(1), yes(2) } + --MAX-ACCESS read-write + --STATUS current + --DESCRIPTION + -- "Adjust time using NTP server." + --::= { networkTime 8 } + +loginAllowTimes OBJECT-TYPE + SYNTAX INTEGER (1..99) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set time of login faliure." + ::= { loginFailures 1 } + +loginTimeOut OBJECT-TYPE + SYNTAX INTEGER (1..240) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set login time out." + ::= { loginFailures 2 } + +icmpEnabled OBJECT-TYPE + SYNTAX INTEGER { no(1), yes(2) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set status of ICMP." + ::= { workingMode 1 } + +--multiUserEnabled OBJECT-TYPE + --SYNTAX INTEGER { no(1), yes(2) } + --MAX-ACCESS read-write + --STATUS current + --DESCRIPTION + -- "Display or set status of multi-user operation." + --::= { workingMode 2 } + +--browserEnabled OBJECT-TYPE + --SYNTAX INTEGER { no(1), yes(2) } + --MAX-ACCESS read-write + --STATUS current + --DESCRIPTION + -- "Display or set status of browser." + --::= { workingMode 3 } + +minUserNameLen OBJECT-TYPE + SYNTAX INTEGER (1..16) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set minimum length of user name." + ::= { accountPolicy 1 } + +minUserPwdLen OBJECT-TYPE + SYNTAX INTEGER (1..16) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set minimum length of user password. + " + ::= { accountPolicy 2 } + +upperCaseEnabled OBJECT-TYPE + SYNTAX INTEGER { no(1), yes(2) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set one upper case rule in user password." + ::= { accountPolicy 3 } + +lowerCaseEnabled OBJECT-TYPE + SYNTAX INTEGER { no(1), yes(2) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set one lower case rule in user password." + ::= { accountPolicy 4 } + +numberEnabled OBJECT-TYPE + SYNTAX INTEGER { no(1), yes(2) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set one number rule in user password." + ::= { accountPolicy 5 } + +disableDuplicateLogin OBJECT-TYPE + SYNTAX INTEGER { no(1), yes(2) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set status of disabled duplicate login rule." + ::= { accountPolicy 6 } + +loginString OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set a login string. + string length: 0~32 + NOTE: Input string as /empty to set this object to NULL. + " + ::= { loginRestriction 1 } + +ipFilterEnabled OBJECT-TYPE + SYNTAX INTEGER { no(1), yes(2) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set status of ip filter." + ::= { ipFilter 1 } + +ipFilterRule OBJECT-TYPE + SYNTAX INTEGER { include(1), exclude(2) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set status of ip filter rule." + ::= { ipFilter 2 } + +ipFilterTable OBJECT-TYPE + SYNTAX SEQUENCE OF IpFilterEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A list of restricted ip." + ::= { ipFilter 3 } + +ipFilterEntry OBJECT-TYPE + SYNTAX IpFilterEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Status and parameter values for a PE's restricted IP." + INDEX { ipFilterIndex } + ::= { ipFilterTable 1 } + +IpFilterEntry ::= + SEQUENCE { + ipFilterIndex + INTEGER, + ipFilterFrom + IpAddress, + ipFilterTo + IpAddress + } + +ipFilterIndex OBJECT-TYPE + SYNTAX INTEGER (1..5) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The value of index for the ip filter. + " + ::= { ipFilterEntry 1 } + +ipFilterFrom OBJECT-TYPE + SYNTAX IpAddress + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "A set of restricted ip. + ex. 192.168.0.1 + + Note: Users must follow in order to set the ip address. + Note: To clear the settings to set the ip 0.0.0.0 + " + ::= { ipFilterEntry 2 } + +ipFilterTo OBJECT-TYPE + SYNTAX IpAddress + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "A set of restricted ip. + ex. 192.168.0.255 + + Note: Users must follow in order to set the ip address. + Note: To clear the settings to set the ip 0.0.0.0 + " + ::= { ipFilterEntry 3 } + +macFilterEnabled OBJECT-TYPE + SYNTAX INTEGER { no(1), yes(2) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set status of mac filter." + ::= { macFilter 1 } + +macFilterRule OBJECT-TYPE + SYNTAX INTEGER { include(1), exclude(2) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set status of mac filter rule." + ::= { macFilter 2 } + +macFilterTable OBJECT-TYPE + SYNTAX SEQUENCE OF MacFilterEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A list of restricted mac." + ::= { macFilter 3 } + +macFilterEntry OBJECT-TYPE + SYNTAX MacFilterEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Status and parameter values for a PE's restricted MAC." + INDEX { macFilterIndex } + ::= { macFilterTable 1 } + +MacFilterEntry ::= + SEQUENCE { + macFilterIndex + INTEGER, + macFilterSet + DisplayString + } + +macFilterIndex OBJECT-TYPE + SYNTAX INTEGER (1..5) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The value of index for the mac filter. + " + ::= { macFilterEntry 1 } + +macFilterSet OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "A set of restricted mac. + string length: 12 + ex. 004854655511 + + Note: Users must follow in order to set the MAC address. + Note: To clear the settings to set the MAC 000000000000 + " + ::= { macFilterEntry 2 } + +--LocalAuth OBJECT-TYPE + --SYNTAX INTEGER { no(1), yes(2) } + --MAX-ACCESS read-write + --STATUS current + --DESCRIPTION + -- "Display or set status of disable local authentication." + --::= { authentication 1 } + +radiusEnabled OBJECT-TYPE + SYNTAX INTEGER { no(1), yes(2) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set status of RADIUS server." + ::= { radius 1 } + +preferRadiusIp OBJECT-TYPE + SYNTAX IpAddress + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set prefer RADIUS server IP." + ::= { radius 2 } + +preferRadiusPort OBJECT-TYPE + SYNTAX INTEGER (1..65535) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set prefer RADIUS server port." + ::= { radius 3 } + +alternateRadiusIp OBJECT-TYPE + SYNTAX IpAddress + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set alternative RADIUS server IP." + ::= { radius 4 } + +alternateRadiusPort OBJECT-TYPE + SYNTAX INTEGER (1..65535) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set alternative RADIUS server port." + ::= { radius 5 } + +radiusTimeOut OBJECT-TYPE + SYNTAX INTEGER (1..60) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set time out of authentication using RADIUS server. + The unit is sec. + " + ::= { radius 6 } + +radiusRetry OBJECT-TYPE + SYNTAX INTEGER (0..10) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set retry times of authentication using RADIUS server." + ::= { radius 7 } + +radiusSecret OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set shared secret of RADIUS server. + string length: 6~15 + At least 6 characters. + NOTE: Input string as /empty to set this object to NULL. + " + ::= { radius 8 } + +-- Device Management End + +-- User Management +usrListTable OBJECT-TYPE + SYNTAX SEQUENCE OF UsrListEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A list of user. The number of user is + given by the value of usrcfgNumber." + ::= { userManagement 1 } + +usrListEntry OBJECT-TYPE + SYNTAX UsrListEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Status and parameter values for a pe8208 user." + INDEX { usrIndex } + ::= { usrListTable 1 } + +UsrListEntry ::= + SEQUENCE { + usrIndex + INTEGER, + usrType + INTEGER, + usrName + DisplayString, + usrPassword + DisplayString, + usrPort1Auth + INTEGER, + usrPort2Auth + INTEGER, + usrPort3Auth + INTEGER, + usrPort4Auth + INTEGER, + usrPort5Auth + INTEGER, + usrPort6Auth + INTEGER, + usrPort7Auth + INTEGER, + usrPort8Auth + INTEGER, + + usrPort9Auth + INTEGER, + usrPort10Auth + INTEGER, + usrPort11Auth + INTEGER, + usrPort12Auth + INTEGER, + usrPort13Auth + INTEGER, + usrPort14Auth + INTEGER, + usrPort15Auth + INTEGER, + usrPort16Auth + INTEGER, + usrPort17Auth + INTEGER, + usrPort18Auth + INTEGER, + usrPort19Auth + INTEGER, + usrPort20Auth + INTEGER, + usrPort21Auth + INTEGER, + usrPort22Auth + INTEGER, + usrPort23Auth + INTEGER, + usrPort24Auth + INTEGER, + usrPort25Auth + INTEGER, + usrPort26Auth + INTEGER, + usrPort27Auth + INTEGER, + usrPort28Auth + INTEGER, + usrPort29Auth + INTEGER, + usrPort30Auth + INTEGER, + usrPort31Auth + INTEGER, + usrPort32Auth + INTEGER, + usrPort33Auth + INTEGER, + usrPort34Auth + INTEGER, + usrPort35Auth + INTEGER, + usrPort36Auth + INTEGER, + usrPort37Auth + INTEGER, + usrPort38Auth + INTEGER, + usrPort39Auth + INTEGER, + usrPort40Auth + INTEGER, + usrPort41Auth + INTEGER, + usrPort42Auth + INTEGER, + usrEnable + INTEGER + } + +usrIndex OBJECT-TYPE + SYNTAX INTEGER (1..9) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The value of usrIndex for the user. We have 1 administrator and 8 users. + The index 9 will be the administrator. + " + ::= { usrListEntry 1 } + +usrType OBJECT-TYPE + SYNTAX INTEGER { administrator(1), user(2)} + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The user's type." + ::= { usrListEntry 2 } + +usrName OBJECT-TYPE + SYNTAX DisplayString (SIZE (1..16)) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "A textual string containing name of the user. + string length: 1~16 + " + ::= { usrListEntry 3 } + +usrPassword OBJECT-TYPE + SYNTAX DisplayString (SIZE (1..16)) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "A textual string containing password of the user. + string length: 1~16 + " + ::= { usrListEntry 4 } + +usrPort1Auth OBJECT-TYPE + SYNTAX INTEGER { disable(1), view(2), modify(3), not-support(4) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set this user's outlet 1 authority. + Port in the pe of series represents outlet. + Port in the Energy monitor of series represents a bank or a pdu." + ::= { usrListEntry 5 } +usrPort2Auth OBJECT-TYPE + SYNTAX INTEGER { disable(1), view(2), modify(3), not-support(4) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set this user's outlet 2 authority. + Port in the pe of series represents outlet. + Port in the Energy monitor of series represents a bank or a pdu." + ::= { usrListEntry 6 } +usrPort3Auth OBJECT-TYPE + SYNTAX INTEGER { disable(1), view(2), modify(3), not-support(4) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set this user's outlet 3 authority. + Port in the pe of series represents outlet. + Port in the Energy monitor of series represents a bank or a pdu." + ::= { usrListEntry 7 } +usrPort4Auth OBJECT-TYPE + SYNTAX INTEGER { disable(1), view(2), modify(3), not-support(4) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set this user's outlet 4 authority. + Port in the pe of series represents outlet. + Port in the Energy monitor of series represents a bank or a pdu." + ::= { usrListEntry 8 } +usrPort5Auth OBJECT-TYPE + SYNTAX INTEGER { disable(1), view(2), modify(3), not-support(4) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set this user's outlet 5 authority. + Port in the pe of series represents outlet. + Port in the Energy monitor of series represents a bank or a pdu." + ::= { usrListEntry 9 } +usrPort6Auth OBJECT-TYPE + SYNTAX INTEGER { disable(1), view(2), modify(3), not-support(4) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Dispaly or set this user's outlet 6 authority. + Port in the pe of series represents outlet. + Port in the Energy monitor of series represents a bank or a pdu." + ::= { usrListEntry 10 } +usrPort7Auth OBJECT-TYPE + SYNTAX INTEGER { disable(1), view(2), modify(3), not-support(4) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set this user's outlet 7 authority. + Port in the pe of series represents outlet. + Port in the Energy monitor of series represents a bank or a pdu." + ::= { usrListEntry 11 } +usrPort8Auth OBJECT-TYPE + SYNTAX INTEGER { disable(1), view(2), modify(3), not-support(4) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set this user's outlet 8 authority. + Port in the pe of series represents outlet. + Port in the Energy monitor of series represents a bank or a pdu." + ::= { usrListEntry 12 } +usrEnable OBJECT-TYPE + SYNTAX INTEGER { disable(1), enable(2) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set this user is enable or not" + ::= { usrListEntry 47 } + +usrPort9Auth OBJECT-TYPE + SYNTAX INTEGER { disable(1), view(2), modify(3), not-support(4) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set this user's outlet 9 authority. + Port in the pe of series represents outlet. + Port in the Energy monitor of series represents a bank or a pdu." + ::= { usrListEntry 13 } + +usrPort10Auth OBJECT-TYPE + SYNTAX INTEGER { disable(1), view(2), modify(3), not-support(4) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set this user's outlet 10 authority. + Port in the pe of series represents outlet. + Port in the Energy monitor of series represents a bank or a pdu." + ::= { usrListEntry 14 } + +usrPort11Auth OBJECT-TYPE + SYNTAX INTEGER { disable(1), view(2), modify(3), not-support(4) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set this user's outlet 11 authority. + Port in the pe of series represents outlet. + Port in the Energy monitor of series represents a bank or a pdu." + ::= { usrListEntry 15 } + +usrPort12Auth OBJECT-TYPE + SYNTAX INTEGER { disable(1), view(2), modify(3), not-support(4) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set this user's outlet 12 authority. + Port in the pe of series represents outlet. + Port in the Energy monitor of series represents a bank or a pdu." + ::= { usrListEntry 16 } + +usrPort13Auth OBJECT-TYPE + SYNTAX INTEGER { disable(1), view(2), modify(3), not-support(4) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set this user's outlet 13 authority. + Port in the pe of series represents outlet. + Port in the Energy monitor of series represents a bank or a pdu." + ::= { usrListEntry 17 } + + +usrPort14Auth OBJECT-TYPE + SYNTAX INTEGER { disable(1), view(2), modify(3), not-support(4) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set this user's outlet 14 authority. + Port in the pe of series represents outlet. + Port in the Energy monitor of series represents a bank or a pdu." + ::= { usrListEntry 18 } + +usrPort15Auth OBJECT-TYPE + SYNTAX INTEGER { disable(1), view(2), modify(3), not-support(4) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set this user's outlet 15 authority. + Port in the pe of series represents outlet. + Port in the Energy monitor of series represents a bank or a pdu." + ::= { usrListEntry 19 } + +usrPort16Auth OBJECT-TYPE + SYNTAX INTEGER { disable(1), view(2), modify(3), not-support(4) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set this user's outlet 16 authority. + Port in the pe of series represents outlet. + Port in the Energy monitor of series represents a bank or a pdu." + ::= { usrListEntry 20 } + +usrPort17Auth OBJECT-TYPE + SYNTAX INTEGER { disable(1), view(2), modify(3), not-support(4) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set this user's outlet 17 authority. + Port in the pe of series represents outlet. + Port in the Energy monitor of series represents a bank or a pdu." + ::= { usrListEntry 21 } + +usrPort18Auth OBJECT-TYPE + SYNTAX INTEGER { disable(1), view(2), modify(3), not-support(4) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set this user's outlet 18 authority. + Port in the pe of series represents outlet. + Port in the Energy monitor of series represents a bank or a pdu." + ::= { usrListEntry 22 } + +usrPort19Auth OBJECT-TYPE + SYNTAX INTEGER { disable(1), view(2), modify(3), not-support(4) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set this user's outlet 19 authority. + Port in the pe of series represents outlet. + Port in the Energy monitor of series represents a bank or a pdu." + ::= { usrListEntry 23 } + +usrPort20Auth OBJECT-TYPE + SYNTAX INTEGER { disable(1), view(2), modify(3), not-support(4) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set this user's outlet 20 authority. + Port in the pe of series represents outlet. + Port in the Energy monitor of series represents a bank or a pdu." + ::= { usrListEntry 24 } + +usrPort21Auth OBJECT-TYPE + SYNTAX INTEGER { disable(1), view(2), modify(3), not-support(4) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set this user's outlet 21 authority. + Port in the pe of series represents outlet. + Port in the Energy monitor of series represents a bank or a pdu." + ::= { usrListEntry 25 } + +usrPort22Auth OBJECT-TYPE + SYNTAX INTEGER { disable(1), view(2), modify(3), not-support(4) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set this user's outlet 22 authority. + Port in the pe of series represents outlet. + Port in the Energy monitor of series represents a bank or a pdu." + ::= { usrListEntry 26 } + +usrPort23Auth OBJECT-TYPE + SYNTAX INTEGER { disable(1), view(2), modify(3), not-support(4) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set this user's outlet 23 authority. + Port in the pe of series represents outlet. + Port in the Energy monitor of series represents a bank or a pdu." + ::= { usrListEntry 27 } + +usrPort24Auth OBJECT-TYPE + SYNTAX INTEGER { disable(1), view(2), modify(3), not-support(4) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set this user's outlet 24 authority. + Port in the pe of series represents outlet. + Port in the Energy monitor of series represents a bank or a pdu." + ::= { usrListEntry 28 } + +usrPort25Auth OBJECT-TYPE + SYNTAX INTEGER { disable(1), view(2), modify(3), not-support(4) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set this user's outlet 25 authority. + Port in the pe of series represents outlet. + Port in the Energy monitor of series represents a bank or a pdu." + ::= { usrListEntry 29 } + +usrPort26Auth OBJECT-TYPE + SYNTAX INTEGER { disable(1), view(2), modify(3), not-support(4) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set this user's outlet 26 authority. + Port in the pe of series represents outlet. + Port in the Energy monitor of series represents a bank or a pdu." + ::= { usrListEntry 30 } + +usrPort27Auth OBJECT-TYPE + SYNTAX INTEGER { disable(1), view(2), modify(3), not-support(4) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set this user's outlet 27 authority. + Port in the pe of series represents outlet. + Port in the Energy monitor of series represents a bank or a pdu." + ::= { usrListEntry 31 } +usrPort28Auth OBJECT-TYPE + SYNTAX INTEGER { disable(1), view(2), modify(3), not-support(4) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set this user's outlet 28 authority. + Port in the pe of series represents outlet. + Port in the Energy monitor of series represents a bank or a pdu." + ::= { usrListEntry 32 } + +usrPort29Auth OBJECT-TYPE + SYNTAX INTEGER { disable(1), view(2), modify(3), not-support(4) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set this user's outlet 29 authority. + Port in the pe of series represents outlet. + Port in the Energy monitor of series represents a bank or a pdu." + ::= { usrListEntry 33 } + +usrPort30Auth OBJECT-TYPE + SYNTAX INTEGER { disable(1), view(2), modify(3), not-support(4) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set this user's outlet 30 authority. + Port in the pe of series represents outlet. + Port in the Energy monitor of series represents a bank or a pdu." + ::= { usrListEntry 34 } + +usrPort31Auth OBJECT-TYPE + SYNTAX INTEGER { disable(1), view(2), modify(3), not-support(4) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set this user's outlet 31 authority + Port in the pe of series represents outlet. + Port in the Energy monitor of series represents a bank or a pdu." + ::= { usrListEntry 35 } + +usrPort32Auth OBJECT-TYPE + SYNTAX INTEGER { disable(1), view(2), modify(3), not-support(4) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set this user's outlet 32 authority + Port in the pe of series represents outlet. + Port in the Energy monitor of series represents a bank or a pdu." + ::= { usrListEntry 36 } + +usrPort33Auth OBJECT-TYPE + SYNTAX INTEGER { disable(1), view(2), modify(3), not-support(4) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set this user's outlet 33 authority + Port in the pe of series represents outlet. + Port in the Energy monitor of series represents a bank or a pdu." + ::= { usrListEntry 37 } + +usrPort34Auth OBJECT-TYPE + SYNTAX INTEGER { disable(1), view(2), modify(3), not-support(4) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set this user's outlet 34 authority + Port in the pe of series represents outlet. + Port in the Energy monitor of series represents a bank or a pdu." + ::= { usrListEntry 38 } + +usrPort35Auth OBJECT-TYPE + SYNTAX INTEGER { disable(1), view(2), modify(3), not-support(4) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set this user's outlet 35 authority + Port in the pe of series represents outlet. + Port in the Energy monitor of series represents a bank or a pdu." + ::= { usrListEntry 39 } + +usrPort36Auth OBJECT-TYPE + SYNTAX INTEGER { disable(1), view(2), modify(3), not-support(4) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set this user's outlet 36 authority + Port in the pe of series represents outlet. + Port in the Energy monitor of series represents a bank or a pdu." + ::= { usrListEntry 40 } + +usrPort37Auth OBJECT-TYPE + SYNTAX INTEGER { disable(1), view(2), modify(3), not-support(4) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set this user's outlet 37 authority + Port in the pe of series represents outlet. + Port in the Energy monitor of series represents a bank or a pdu." + ::= { usrListEntry 41 } + +usrPort38Auth OBJECT-TYPE + SYNTAX INTEGER { disable(1), view(2), modify(3), not-support(4) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set this user's outlet 38 authority + Port in the pe of series represents outlet. + Port in the Energy monitor of series represents a bank or a pdu." + ::= { usrListEntry 42 } + +usrPort39Auth OBJECT-TYPE + SYNTAX INTEGER { disable(1), view(2), modify(3), not-support(4) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set this user's outlet 39 authority + Port in the pe of series represents outlet. + Port in the Energy monitor of series represents a bank or a pdu." + ::= { usrListEntry 43 } + +usrPort40Auth OBJECT-TYPE + SYNTAX INTEGER { disable(1), view(2), modify(3), not-support(4) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set this user's outlet 40 authority + Port in the pe of series represents outlet. + Port in the Energy monitor of series represents a bank or a pdu." + ::= { usrListEntry 44 } + +usrPort41Auth OBJECT-TYPE + SYNTAX INTEGER { disable(1), view(2), modify(3), not-support(4) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set this user's outlet 41 authority + Port in the pe of series represents outlet. + Port in the Energy monitor of series represents a bank or a pdu." + ::= { usrListEntry 45 } + +usrPort42Auth OBJECT-TYPE + SYNTAX INTEGER { disable(1), view(2), modify(3), not-support(4) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Display or set this user's outlet 42 authority + Port in the pe of series represents outlet. + Port in the Energy monitor of series represents a bank or a pdu." + ::= { usrListEntry 46 } + +-- User Management End + +-- DeviceLock +--communityLock OBJECT-TYPE +-- SYNTAX DisplayString +-- MAX-ACCESS read-write +-- STATUS current +-- DESCRIPTION +-- "Change SNMPV1 or SNMPV2 community for California passes law. +-- Please follow the format as readcommunity||writecommunity" +-- ::= { deviceLock 1 } + +--passwordLock OBJECT-TYPE +-- SYNTAX DisplayString +-- MAX-ACCESS read-write +-- STATUS current +-- DESCRIPTION +-- "Change SNMPV3 password for California passes law. +-- Please follow the format as authpassword||privpassword" +-- ::= { deviceLock 2 } +-- DeviceLock End + +-- SNMPv3 USM Settings +--snmpv3UsmUserTable OBJECT-TYPE +-- SYNTAX SEQUENCE OF Snmpv3UsmUserEntry +-- MAX-ACCESS not-accessible +-- STATUS current +-- DESCRIPTION "This table is used to configure PE SNMPv3 USM. +-- To get the SNMPv3 access, One need to configure security +-- name,authentication,auth password,priv protocol and priv +-- password. +-- " +-- ::= { snmp 2 } + +--snmpv3UsmUserEntry OBJECT-TYPE +-- SYNTAX Snmpv3UsmUserEntry +-- MAX-ACCESS not-accessible +-- STATUS current +-- DESCRIPTION "A user configured for the User-based +-- Security Model. +-- " +-- INDEX { usmIndex } +-- ::= { snmpv3UsmUserTable 1 } + +--Snmpv3UsmUserEntry ::= SEQUENCE { +-- usmIndex INTEGER, +-- usmSecurityName SnmpAdminString, +-- smAuthProtocol SNMPv3UsmAuthPrivProtocol, +-- usmPrivPassword SnmpAdminString +-- } + +--usmIndex OBJECT-TYPE +-- SYNTAX INTEGER (1) +-- MAX-ACCESS not-accessible +-- STATUS current +-- DESCRIPTION "Usm configuration index. " +-- ::= { snmpv3UsmUserEntry 1 } + + +--usmSecurityName OBJECT-TYPE +-- SYNTAX SnmpAdminString +-- MAX-ACCESS read-only +-- STATUS current +-- DESCRIPTION "A human readable string representing the user in +-- Security Model independent format. + +-- The default transformation of the User-based Security +-- Model dependent security ID to the securityName and +-- vice versa is the identity function so that the +-- securityName is the same as the userName. +-- " +-- ::= { snmpv3UsmUserEntry 2 } + + +--usmKeyAlgorithm OBJECT-TYPE +-- SYNTAX SNMPv3UsmAuthPrivProtocol +-- MAX-ACCESS read-only +-- STATUS current +-- DESCRIPTION " +-- If usmAuthProtocol == HMACMD5Auth , supports MD5 AuthKey and PrivKey +-- If usmAuthProtocol == HMACSHAAuth, supports SHA AuthKey and PrivKey +-- " +-- ::= { snmpv3UsmUserEntry 3 } + +--usmPrivProtocol OBJECT-TYPE +-- SYNTAX SNMPv3UsmAuthPrivProtocol +-- MAX-ACCESS read-only + -- STATUS current + -- DESCRIPTION " A privacy protocol to provide encryption and decryption +-- SNMPv3 pdu. + -- " + -- ::= { snmpv3UsmUserEntry 4 } + +--usmPrivPassword OBJECT-TYPE +-- SYNTAX SnmpAdminString +-- MAX-ACCESS read-only +-- STATUS current +-- DESCRIPTION "An user's privacy password, Associated protocol +-- and a secret key is used to establish a connection +-- for the snmp agent and manager commnucation. +-- " +-- ::= { snmpv3UsmUserEntry 4 } + + +-- SNMPv3 Target MIB + +--snmpv3TargetTable OBJECT-TYPE +-- SYNTAX SEQUENCE OF Snmpv3TargetEntry +-- MAX-ACCESS not-accessible +-- STATUS current +-- DESCRIPTION + -- "A table of SNMP target information to be used + -- in the generation of SNMP trap messages." + -- ::= { snmp 3 } + +--snmpv3TargetEntry OBJECT-TYPE +-- SYNTAX Snmpv3TargetEntry +-- MAX-ACCESS not-accessible +-- STATUS current +-- DESCRIPTION +-- "A set of SNMP target information. +-- " +-- INDEX { snmpv3TargetIndex } +-- ::= { snmpv3TargetTable 1 } + +--Snmpv3TargetEntry ::= SEQUENCE { +-- snmpv3TargetIndex INTEGER, +-- snmpv3TargetMPModel SnmpMessageProcessingModel, +-- snmpv3TargetSecurityModel SnmpSecurityModel, + -- snmpv3TargetSecurityName SnmpAdminString +--} +--snmpv3TargetIndex OBJECT-TYPE + -- SYNTAX INTEGER(1) + -- MAX-ACCESS not-accessible + -- STATUS current + -- DESCRIPTION + -- "The locally arbitrary, but unique identifier associated + -- with this snmpv3TargetEntry." + -- ::= { snmpv3TargetEntry 1 } + +--snmpv3TargetMPModel OBJECT-TYPE + -- SYNTAX SnmpMessageProcessingModel + -- MAX-ACCESS read-only + -- STATUS current + -- DESCRIPTION + -- "The Message Processing Model to be used when generating + -- SNMP messages using this entry." + -- ::= { snmpv3TargetEntry 2 } + +--snmpv3TargetSecurityModel OBJECT-TYPE + -- SYNTAX SnmpSecurityModel (1..2147483647) + -- MAX-ACCESS read-only + -- STATUS current + -- DESCRIPTION + -- "The Security Model to be used when generating SNMP + -- messages using this entry. An implementation may + -- choose to return an inconsistentValue error if an + -- attempt is made to set this variable to a value + -- for a security model which the implementation does + -- not support." + -- ::= { snmpv3TargetEntry 3 } + +--snmpv3TargetSecurityName OBJECT-TYPE + -- SYNTAX SnmpAdminString + -- MAX-ACCESS read-only + -- STATUS current + -- DESCRIPTION + -- "The securityName which identifies the Principal on + -- whose behalf SNMP messages will be generated using + -- this entry." + -- ::= { snmpv3TargetEntry 4 } + +--snmpv3TargetSecurityLevel OBJECT-TYPE + -- SYNTAX SnmpSecurityLevel + -- MAX-ACCESS read-only + -- STATUS current + -- DESCRIPTION + -- "The Level of Security to be used when generating + -- SNMP messages using this entry." + -- ::= { snmpv3TargetEntry 5 } + +-- Custom Trap Message + +customTrapMSG NOTIFICATION-TYPE + STATUS current + --OBJECTS { customTrapMSG } + DESCRIPTION "Display custom trap message." + ::= { pe 5 } + +rebootDevice OBJECT-TYPE + SYNTAX INTEGER { no(1), yes(2) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION "Reboot PE Device" + ::= { pe 6 } +-- CPM +--modelName OBJECT-TYPE +-- SYNTAX DisplayString +-- MAX-ACCESS read-only +-- STATUS current +-- DESCRIPTION +-- "Indicate CPM device model name." +-- ::= { CPM 1 } + +--cpmName OBJECT-TYPE +-- SYNTAX DisplayString +-- MAX-ACCESS read-write +-- STATUS current +-- DESCRIPTION +-- "The name of CPM device. +-- string length: 1~39 +-- NOTE: Input string as /empty to set this object to NULL. +-- " +-- ::= { CPM 2 } + +--cpmswitchable OBJECT-TYPE +-- SYNTAX INTEGER { no(1), yes(2) } +-- MAX-ACCESS read-only +-- STATUS current +-- DESCRIPTION +-- " Switchable or not. " +-- ::= { CPM 3 } + +--cpmPDUreading OBJECT-TYPE +-- SYNTAX INTEGER { no(1), yes(2) } +-- MAX-ACCESS read-only +-- STATUS current +-- DESCRIPTION +-- " CPM is per-PDU reading or not." +-- ::= { CPM 4 } + +--cpmSensornumber OBJECT-TYPE +-- SYNTAX INTEGER +-- MAX-ACCESS read-only +-- STATUS current +-- DESCRIPTION +-- " CPM's Sensor number." +-- ::= { CPM 5 } + +--cpmOutletnumber OBJECT-TYPE +-- SYNTAX INTEGER +-- MAX-ACCESS read-only +-- STATUS current +-- DESCRIPTION +-- " CPM's Outlet number." +-- ::= { CPM 6 } + +--cpmbreaker OBJECT-TYPE + --SYNTAX INTEGER { off(1), on(2) } + --MAX-ACCESS read-only + --STATUS current + --DESCRIPTION + -- "CPM's breaker status." + --::= { CPM 7 } + +-- Device +--cpmdeviceValueTable OBJECT-TYPE +-- SYNTAX SEQUENCE OF cpmDeviceValueEntry +-- MAX-ACCESS not-accessible +-- STATUS current +-- DESCRIPTION +-- "Device value table. This table displays device's current. +-- " +-- ::= { CPMDevice 1 } + +--cpmdeviceValueEntry OBJECT-TYPE +-- SYNTAX cpmDeviceValueEntry +-- MAX-ACCESS not-accessible +-- STATUS current +-- DESCRIPTION +-- "Single deviceValue entry containing device info." +-- INDEX { cpmdeviceValueIndex } +-- ::= { cpmdeviceValueTable 1 } + +--cpmDeviceValueEntry ::= +-- SEQUENCE { +-- cpmdeviceValueIndex +-- INTEGER, +-- cpmdeviceCurrent +-- DisplayString, + --cpmdeviceVoltage + -- DisplayString, + --cpmdevicePower + -- DisplayString, + --cpmdevicePowerDissipation + -- DisplayString, + --cpminputMaxVoltage + -- INTEGER, +-- cpminputMaxCurrent +-- INTEGER + --cpmpowerCapacity + -- INTEGER + +-- } + +--cpmdeviceValueIndex OBJECT-TYPE +-- SYNTAX INTEGER (1) +-- MAX-ACCESS not-accessible +-- STATUS current +-- DESCRIPTION +-- "Index of device Value." +-- ::= { cpmdeviceValueEntry 1 } + +--cpmdeviceCurrent OBJECT-TYPE +-- SYNTAX DisplayString +-- MAX-ACCESS read-only +-- STATUS current +-- DESCRIPTION +-- "Device electric current value. +-- " +-- ::= { cpmdeviceValueEntry 2 } + +--cpmdeviceVoltage OBJECT-TYPE +-- SYNTAX DisplayString +-- MAX-ACCESS read-only +-- STATUS current +-- DESCRIPTION +-- "Device voltage value." +-- ::= { cpmdeviceValueEntry 3 } +--cpmdevicePower OBJECT-TYPE +-- SYNTAX DisplayString +-- MAX-ACCESS read-only +-- STATUS current +-- DESCRIPTION +-- "Device power value." +-- ::= { cpmdeviceValueEntry 4 } + +--cpmdevicePowerDissipation OBJECT-TYPE +-- SYNTAX DisplayString +-- MAX-ACCESS read-only +-- STATUS current +-- DESCRIPTION +-- "Device power dissipation value." +-- ::= { cpmdeviceValueEntry 5 } + +--cpminputMaxVoltage OBJECT-TYPE +-- SYNTAX INTEGER +-- MAX-ACCESS read-only +-- STATUS current +-- DESCRIPTION +-- "Device input Voltage value. unit:(V)" +-- ::= { cpmdeviceValueEntry 6 } + +--cpminputMaxCurrent OBJECT-TYPE +-- SYNTAX INTEGER +-- MAX-ACCESS read-only +-- STATUS current +-- DESCRIPTION +-- "Device input Current value. unit:(A)" +-- ::= { cpmdeviceValueEntry 7 } + +--cpmpowerCapacity OBJECT-TYPE +-- SYNTAX INTEGER +-- MAX-ACCESS read-only +-- STATUS current +-- DESCRIPTION +-- "Device power Capacity value.unit:(VA)" +-- ::= { cpmdeviceValueEntry 8 } + +--cpmdeviceConfigTable OBJECT-TYPE +-- SYNTAX SEQUENCE OF cpmDeviceConfigEntry +-- MAX-ACCESS not-accessible +-- STATUS current +-- DESCRIPTION +-- "Device configuration table" +-- ::= { CPMDevice 2 } + +--cpmdeviceConfigEntry OBJECT-TYPE +-- SYNTAX cpmDeviceConfigEntry +-- MAX-ACCESS not-accessible +-- STATUS current +-- DESCRIPTION +-- "Single deviceConfig entry containing device info." +-- INDEX { cpmdeviceConfigIndex } +-- ::= { cpmdeviceConfigTable 1 } + +--cpmDeviceConfigEntry ::= +-- SEQUENCE { +-- cpmdeviceConfigIndex +-- INTEGER, + --cpmdeviceMinCurMT + -- INTEGER, +-- cpmdeviceMaxCurMT +-- INTEGER + --cpmdeviceMinVolMT + -- INTEGER, + --cpmdeviceMaxVolMT + -- INTEGER, +-- } + +--cpmdeviceConfigIndex OBJECT-TYPE +-- SYNTAX INTEGER (1) +-- MAX-ACCESS not-accessible +-- STATUS current +-- DESCRIPTION +-- "Index of deviceConfig" +-- ::= { cpmdeviceConfigEntry 1 } + +--cpmdeviceMinCurMT OBJECT-TYPE +-- SYNTAX INTEGER +-- MAX-ACCESS read-write +-- STATUS current +-- DESCRIPTION +-- "Display or set device minimum electric current measurement threshold. +-- When this value is -3000,it indicate this is NULL. +-- When set this value to -3000, indicate set this object as NULL. +-- range:0.0~32.0 represents:0~320 +-- NOTICE:Minimum threshold should be setted smaller than Maxima threshold +-- " +-- ::= { cpmdeviceConfigEntry 2 } + +--cpmdeviceMaxCurMT OBJECT-TYPE +-- SYNTAX INTEGER +-- MAX-ACCESS read-write +-- STATUS current +-- DESCRIPTION +-- "Display or set device maximum electric current measurement threshold. +-- When this value is -3000,it indicate this is NULL. +-- When set this value to -3000, indicate set this object as NULL. +-- Example: range 0.0~32.0 represents: 0~320 + +-- NOTICE:Minimum threshold should be setted smaller than Maxima threshold +-- " +-- ::= { cpmdeviceConfigEntry 3 } + +--cpmdeviceMinVolMT OBJECT-TYPE +-- SYNTAX INTEGER (900..2600 | -3000) +-- MAX-ACCESS read-write +-- STATUS current +-- DESCRIPTION +-- "Display or set device minimum voltage measurement threshold. +-- range:90.0~260.0 represents:900~2600 +-- When this value is -3000,it indicate this is NULL. +-- When set this value to -3000, indicate set this object as NULL. +-- NOTICE:Minimum threshold should be setted smaller than Maxima threshold +-- " +-- ::= { cpmdeviceConfigEntry 4 } + +--cpmdeviceMaxVolMT OBJECT-TYPE +-- SYNTAX INTEGER (900..2600 | -3000) +-- MAX-ACCESS read-write +-- STATUS current +-- DESCRIPTION +-- "Display or set device maximum voltage measurement threshold. +-- range:90.0~260.0 represents:900~2600 +-- When this value is -3000,it indicate this is NULL. +-- When set this value to -3000, indicate set this object as NULL. +-- NOTICE:Minimum threshold should be setted smaller than Maxima threshold +-- " +-- ::= { cpmdeviceConfigEntry 5 } + + + +-- Sensor +--cpmSensorValueTable OBJECT-TYPE +-- SYNTAX SEQUENCE OF cpmSensorValueEntry +-- MAX-ACCESS not-accessible +-- STATUS current +-- DESCRIPTION +-- "CPM's sensor value table. This table displays sensor's temperature, humidity and +-- pressure. +-- " +-- ::= { Sensor 1 } + +--cpmSensorValueEntry OBJECT-TYPE +-- SYNTAX cpmSensorValueEntry +-- MAX-ACCESS not-accessible +-- STATUS current +-- DESCRIPTION +-- "CPM's sensor value entry containing Sensor info." +-- INDEX { cpmSensorValueIndex } +-- ::= { cpmSensorValueTable 1 } + +--cpmSensorValueEntry ::= +-- SEQUENCE { +-- cpmSensorValueIndex +-- INTEGER, +-- cpmSensorTemperature +-- DisplayString, +-- cpmSensorHumidity +-- DisplayString, +-- cpmSensorPressure +-- DisplayString, +-- cpmSensorProperty +-- INTEGER +-- } + +--cpmSensorValueIndex OBJECT-TYPE +-- SYNTAX INTEGER (1..4) +-- MAX-ACCESS not-accessible +-- STATUS current +-- DESCRIPTION +-- "Index of CPM's Sensor number." +-- ::= { cpmSensorValueEntry 1 } + +--cpmSensorTemperature OBJECT-TYPE +-- SYNTAX DisplayString +-- MAX-ACCESS read-only +-- STATUS current +-- DESCRIPTION +-- "CPM's Sensor Temperature value." +-- ::= { cpmSensorValueEntry 2 } + +--cpmSensorHumidity OBJECT-TYPE +-- SYNTAX DisplayString +-- MAX-ACCESS read-only +-- STATUS current +-- DESCRIPTION +-- "CPM's Sensor Humidity value." +-- ::= { cpmSensorValueEntry 3 } + +--cpmSensorPressure OBJECT-TYPE +-- SYNTAX DisplayString +-- MAX-ACCESS read-only +-- STATUS current +-- DESCRIPTION +-- "CPM's Sensor Pressure value." +-- ::= { cpmSensorValueEntry 4 } + +--cpmSensorProperty OBJECT-TYPE +-- SYNTAX INTEGER { intake(1), exhaust(2) } +-- MAX-ACCESS read-only +-- STATUS current +-- DESCRIPTION +-- "CPM's Sensor Property." +-- ::= { cpmSensorValueEntry 5 } + +--cpmSensorThresholdTable OBJECT-TYPE +-- SYNTAX SEQUENCE OF cpmSensorThresholdEntry +-- MAX-ACCESS not-accessible +-- STATUS current +-- DESCRIPTION +-- "CPM's Sensor value table" +-- ::= { Sensor 2 } + +--cpmSensorThresholdEntry OBJECT-TYPE +-- SYNTAX cpmSensorThresholdEntry +-- MAX-ACCESS not-accessible +-- STATUS current +-- DESCRIPTION +-- "CPM's sensor threshold entry containing sensor info." +-- INDEX { cpmSensorThresholdIndex } +-- ::= { cpmSensorThresholdTable 1 } + +--cpmSensorThresholdEntry ::= +-- SEQUENCE { +-- cpmSensorThresholdIndex +-- INTEGER, +-- cpmsensorMinTempMT +-- INTEGER, +-- cpmsensorMaxTempMT +-- INTEGER, + +-- cpmsensorMinHumMT +-- INTEGER, +-- cpmsensorMaxHumMT +-- INTEGER, +-- cpmsensorMinPressMT +-- INTEGER, +-- cpmsensorMaxPressMT +-- INTEGER + --sensorTempFlu + --INTEGER, + --sensorHumFlu + --INTEGER, + --sensorPressFlu + --INTEGER +-- } + +--cpmSensorThresholdIndex OBJECT-TYPE +-- SYNTAX INTEGER (1..4) +-- MAX-ACCESS not-accessible +-- STATUS current +-- DESCRIPTION +-- "Index of CPM's sensor number" +-- ::= { cpmSensorThresholdEntry 1 } + +--cpmsensorMinTempMT OBJECT-TYPE +-- SYNTAX INTEGER (-200..600 | -3000) +-- MAX-ACCESS read-write +-- STATUS current +-- DESCRIPTION +-- "Display or set sensor minimum temperature measurement threshold. +-- Example: range 0.0 ~ 60.0 represents 0~600 +-- When this value is -3000,it indicate this is NULL. +-- When set this value to -3000, indicate set this object as NULL. + +-- NOTICE:Minimum threshold should be setted smaller than Maxima threshold. +-- " +-- ::= { cpmSensorThresholdEntry 2 } + +--cpmsensorMaxTempMT OBJECT-TYPE +-- SYNTAX INTEGER (-200..600 | -3000) +-- MAX-ACCESS read-write +-- STATUS current +-- DESCRIPTION +-- "Display or set sensor maximum temperature measurement threshold. +-- Example: range 0.0 ~ 60.0 represents 0~600 +-- When this value is -3000,it indicate this is NULL. +-- When set this value to -3000, indicate set this object as NULL. + +-- NOTICE:Minimum threshold should be setted smaller than Maxima threshold +-- " +-- ::= { cpmSensorThresholdEntry 3 } + +--cpmsensorMinHumMT OBJECT-TYPE +-- SYNTAX INTEGER (150..950 | -3000) +-- MAX-ACCESS read-write +-- STATUS current +-- DESCRIPTION +-- "Display or set sensor minimum humidity measurement threshold. +-- Example: range 15.0 ~ 95.0 represents 150~950 +-- When this value is -3000,it indicate this is NULL. +-- When set this value to -3000, indicate set this object as NULL. + +-- NOTICE:Minimum threshold should be setted smaller than Maxima threshold +-- " +-- ::= { cpmSensorThresholdEntry 4 } +--cpmsensorMaxHumMT OBJECT-TYPE +-- SYNTAX INTEGER (150..950 | -3000) +-- MAX-ACCESS read-write +-- STATUS current +-- DESCRIPTION +-- "Display or set sensor maximum humidity measurement threshold. +-- Example: range 15.0 ~ 95.0 represents 150~950 +-- When this value is -3000,it indicate this is NULL. +-- When set this value to -3000, indicate set this object as NULL. + +-- NOTICE:Minimum threshold should be setted smaller than Maxima threshold +-- " +-- ::= { cpmSensorThresholdEntry 5 } + +--cpmsensorMinPressMT OBJECT-TYPE +-- SYNTAX INTEGER (-2500..2500 | -3000) +-- MAX-ACCESS read-write +-- STATUS current +-- DESCRIPTION +-- "Display or set sensor minimum pressure measurement threshold. +-- Example: range -250.0 ~ 250.0 represents -2500 ~ 2500 +-- When this value is -3000,it indicate this is NULL. +-- When set this value to -3000, indicate set this object as NULL. + +-- NOTICE:Minimum threshold should be setted smaller than Maxima threshold +-- " +-- ::= { cpmSensorThresholdEntry 6 } + +--cpmsensorMaxPressMT OBJECT-TYPE +-- SYNTAX INTEGER (-2500..2500 | -3000) +-- MAX-ACCESS read-write +-- STATUS current +-- DESCRIPTION +-- "Display or set sensor maximum pressure measurement threshold. +-- Example: range -250.0 ~ 250.0 represents -2500 ~ 2500 +-- When this value is -3000,it indicate this is NULL. +-- When set this value to -3000, indicate set this object as NULL. + +-- NOTICE:Minimum threshold should be setted smaller than Maxima threshold +-- " +-- ::= { cpmSensorThresholdEntry 7 } + + +-- pdu + +--cpmPDUValueTable OBJECT-TYPE +-- SYNTAX SEQUENCE OF cpmPDUValueEntry +-- MAX-ACCESS not-accessible +-- STATUS current +-- DESCRIPTION +-- "Display the PDU's current value of CPM" +-- ::= { EnergySensor 1 } + +--cpmPDUValueEntry OBJECT-TYPE +-- SYNTAX cpmPDUValueEntry +-- MAX-ACCESS not-accessible +-- STATUS current +-- DESCRIPTION +-- "CPM's monitor pdu Value entry containing outlet info." +-- INDEX { cpmPDUValueIndex } +-- ::= { cpmPDUValueTable 1 } + +--cpmPDUValueEntry ::= +-- SEQUENCE { +-- cpmPDUValueIndex +-- INTEGER, +-- cpmPDUCurrent +-- DisplayString, + --cpmPDUVoltage + -- DisplayString, + --cpmPDUPower + -- DisplayString, + --cpmPDUPowerDissipation + -- DisplayString, +-- cpmPDUMaxCurrent +-- INTEGER +-- } + +--cpmPDUValueIndex OBJECT-TYPE +-- SYNTAX INTEGER (1..4) +-- MAX-ACCESS not-accessible +-- STATUS current +-- DESCRIPTION +-- "Index of PDU number" +-- ::= { cpmPDUValueEntry 1 } + +--cpmPDUCurrent OBJECT-TYPE +-- SYNTAX DisplayString +-- MAX-ACCESS read-only +-- STATUS current +-- DESCRIPTION +-- "CPM's monitor PDU electric current value" +-- ::= { cpmPDUValueEntry 2 } + +--cpmPDUVoltage OBJECT-TYPE + --SYNTAX DisplayString + --MAX-ACCESS read-only + --STATUS current + --DESCRIPTION + -- "CPM's monitor PDU voltage value" + --::= { cpmPDUValueEntry 3 } + +--cpmPDUPower OBJECT-TYPE + --SYNTAX DisplayString + --MAX-ACCESS read-only + --STATUS current + --DESCRIPTION + -- "CPM's monitor PDU power value" + --::= { cpmPDUValueEntry 4 } + +--cpmPDUPowerDissipation OBJECT-TYPE + --SYNTAX DisplayString + --MAX-ACCESS read-only + --STATUS current + --DESCRIPTION + -- "CPM's monitor PDU power dissipation value" + --::= { cpmPDUValueEntry 5 } + +--cpmPDUMaxCurrent OBJECT-TYPE +-- SYNTAX INTEGER +-- MAX-ACCESS read-only +-- STATUS current +-- DESCRIPTION +-- "CPM's monitor PDU Max Current value. unit: (A)" +-- ::= { cpmPDUValueEntry 6 } + +--cpmBankStatus OBJECT-TYPE +-- SYNTAX INTEGER { noattached(1), attached(2) } +-- MAX-ACCESS read-only +-- STATUS current +-- DESCRIPTION +-- "The status CPM device Bank status." +-- ::= { cpmPDUValueEntry 7 } + + +--cpmPDUConfigTable OBJECT-TYPE +-- SYNTAX SEQUENCE OF cpmPDUConfigEntry +-- MAX-ACCESS not-accessible +-- STATUS current +-- DESCRIPTION +-- "CPM's monitor PDU configuration table" +-- ::= { EnergySensor 2 } + +--cpmPDUConfigEntry OBJECT-TYPE +-- SYNTAX cpmPDUConfigEntry +-- MAX-ACCESS not-accessible +-- STATUS current +-- DESCRIPTION +-- "CPM's monitor PDU config entry containing PDU info." +-- INDEX { cpmPDUConfigIndex } +-- ::= { cpmPDUConfigTable 1 } + +--cpmPDUConfigEntry ::= +-- SEQUENCE { +-- cpmPDUConfigIndex +-- INTEGER, +-- cpmPDUName +-- DisplayString, + --cpmPDUConfirmation + -- INTEGER, + --cpmPDUOnDelayTime + -- INTEGER, + --cpmPDUOffDelayTime + -- INTEGER, + --cpmPDUShutdownMethod + -- INTEGER, + --cpmPDUMAC + -- DisplayString, + --cpmPDUMinCurMT + -- INTEGER, +-- cpmPDUMaxCurMT +-- INTEGER + + --cpmPDUMinVolMT + -- INTEGER, + --cpmPDUMaxVolMT + -- INTEGER, + + +-- } + +--cpmPDUConfigIndex OBJECT-TYPE +-- SYNTAX INTEGER (1..4) +-- MAX-ACCESS not-accessible +-- STATUS current +-- DESCRIPTION +-- "Index of PDU number" +-- ::= { cpmPDUConfigEntry 1 } + +--cpmPDUName OBJECT-TYPE +-- SYNTAX DisplayString +-- MAX-ACCESS read-write +-- STATUS current +-- DESCRIPTION +-- "Display or set the name of pdu. +-- string length: 0~15 +-- NOTE: Input string as /empty to set this object to NULL. +-- " +-- ::= { cpmPDUConfigEntry 2 } + +--cpmPDUConfirmation OBJECT-TYPE + --SYNTAX INTEGER { no(1), yes(2) } + --MAX-ACCESS read-write + --STATUS current + --DESCRIPTION + -- "Display or set the confirmation of outlet." + --::= { cpmPDUConfigEntry 3 } + +--cpmPDUOnDelayTime OBJECT-TYPE + --SYNTAX INTEGER (0..999) + --MAX-ACCESS read-write + --STATUS current + --DESCRIPTION + -- "Display or set the ON delay time of outlet." + --::= { cpmPDUConfigEntry 4 } + +--cpmPDUOffDelayTime OBJECT-TYPE + --SYNTAX INTEGER (0..999) + --MAX-ACCESS read-write + --STATUS current + --DESCRIPTION + -- "Display or set the OFF delay time of outlet." + --::= { cpmPDUConfigEntry 5 } + +--cpmPDUShutdownMethod OBJECT-TYPE + --SYNTAX INTEGER { kill-the-power(1), wake-on-lan(2), after-ac-back(3) } + --MAX-ACCESS read-write + --STATUS current + --DESCRIPTION + -- "Display or set the shutdown mehtod of outlet." + --::= { cpmPDUConfigEntry 6 } + +--cpmPDUMAC OBJECT-TYPE + --SYNTAX DisplayString + --MAX-ACCESS read-write + --STATUS current + --DESCRIPTION + -- "Display or set the MAC address of ShutdownMethod. + -- string length: 12 + -- " + --::= { cpmPDUConfigEntry 7 } + +--cpmPDUMinCurMT OBJECT-TYPE +-- SYNTAX INTEGER +-- MAX-ACCESS read-write +-- STATUS current +-- DESCRIPTION +-- "Display or set the PDU minimum electric current measurment threshold. +-- Range:0.0 ~16.0 rerpresnts 0~160 +-- When this value is -3000,it indicate this is NULL. +-- When set this value to -3000, indicate set this object as NULL. +-- +-- NOTICE:Minimum threshold should be setted smaller than Maxima threshold +-- " +-- ::= { cpmPDUConfigEntry 3 } + +--cpmPDUMaxCurMT OBJECT-TYPE +-- SYNTAX INTEGER +-- MAX-ACCESS read-write +-- STATUS current +-- DESCRIPTION +-- "Display or set the PDU maximum electric current measurment threshold. +-- Example: range 0.0 ~16.0 represents 0~160 +-- When this value is -3000,it indicate this is NULL. +-- When set this value to -3000, indicate set this object as NULL. + +-- NOTICE:Minimum threshold should be setted smaller than Maxima threshold +-- " +-- ::= { cpmPDUConfigEntry 4 } + +--cpmPDUMinVolMT OBJECT-TYPE + --SYNTAX INTEGER (900..2600) + --MAX-ACCESS read-write + --STATUS current + --DESCRIPTION + -- "Display or set the outlet minimum voltage measurment threshold. + -- Range:90.0 ~260.0 represents 900~2600 + -- When this value is -3000,it indicate this is NULL. + -- When set this value to -3000, indicate set this object as NULL. + -- NOTICE:Minimum threshold should be setted smaller than Maxima threshold + -- " + --::= { cpmPDUConfigEntry 10 } + +--cpmPDUMaxVolMT OBJECT-TYPE + --SYNTAX INTEGER (900..2600) + --MAX-ACCESS read-write + --STATUS current + --DESCRIPTION + -- "Display or set the outlet maximum voltage measurment threshold. + -- Range:90.0 ~260.0 represents 900~2600 + -- When this value is -3000,it indicate this is NULL. + -- When set this value to -3000, indicate set this object as NULL. + -- NOTICE:Minimum threshold should be setted smaller than Maxima threshold + -- " + --::= { cpmPDUConfigEntry 11 } + + +END diff --git a/roles/aten_pdu/files/aten-mqtt-publish.sh b/roles/aten_pdu/files/aten-mqtt-publish.sh new file mode 100755 index 0000000..60803fa --- /dev/null +++ b/roles/aten_pdu/files/aten-mqtt-publish.sh @@ -0,0 +1,93 @@ +#!/bin/sh + +set -eu +umask 077 + +community="public" + +if [ "${1:-}" = "-n" ]; then + _noop=true +else + _noop=false +fi + +mqtt_send() { + topic="$1" + value="$2" + + tlsdir="$(openssl version -d | sed -e 's/^OPENSSLDIR: "\(.\+\)"$/\1/')" + mosquitto_pub -h mqtt02.home.foo.sh -t "$topic" -m "$value" \ + --cafile "${tlsdir}/certs/ca.crt" \ + --key "${tlsdir}/private/$(hostname -f).key" \ + --cert "${tlsdir}/certs/$(hostname -f).crt" +} + +snmp_get() { + host="$1" + key="$2" + snmpget -v 1 -c "$community" "$host" -Oqv -m ATEN-PE-CFG "$key" | tr -d '"' +} + +# only run script if first vrrp interface is in master state +for state in /run/keepalived/*.state ; do + if [ "$(cat "$state")" != "MASTER" ]; then + exit 0 + fi + break +done + +ldapsearch -Q -LLL "(&(objectClass=device)(description=Aten PE*))" cn l | awk ' + { + if ($1 == "cn:") { + cn = $2 + } + if ($1 == "l:") { + l = substr($0, 3) + } + if ($0 == "" && cn != "" && l != "") { + print cn l + cn = "" + l = "" + } + } + ' | while read -r name location +do + snmpwalk -v 1 -c "$community" "$name" -Oq \ + -m ATEN-PE-CFG ATEN-PE-CFG::outletName | while read -r port device + do + port="$(echo "$port" | cut -d '.' -f 2)" + device="$(echo "$device" | tr -d '"')" + case "$device" in + "N/A"|"00 "|"unused") + continue + ;; + esac + if device_name="$(ldapsearch -Q -LLL \ + "(&(objectClass=device)(cn=${device}.*))" cn | awk " + { + if (\$1 == \"cn:\") { + if (name) { + exit 1 + } + name=\$2 + } + } END { + if (!name) { + exit 1 + } + print name + } + ")" ; then + device="$device_name" + fi + for key in Current Power Voltage ; do + topic="home/${location}/${device}/$(echo "$key" | tr '[:upper:]' '[:lower:]')" + value="$(snmp_get "$name" "ATEN-PE-CFG::outlet${key}.${port}")" + if $_noop ; then + echo "${topic} -> ${value}" + else + mqtt_send "$topic" "$value" + fi + done + done +done diff --git a/roles/aten_pdu/meta/main.yml b/roles/aten_pdu/meta/main.yml new file mode 100644 index 0000000..d2f9d51 --- /dev/null +++ b/roles/aten_pdu/meta/main.yml @@ -0,0 +1,3 @@ +--- +dependencies: + - {role: ldap} diff --git a/roles/aten_pdu/tasks/main.yml b/roles/aten_pdu/tasks/main.yml new file mode 100644 index 0000000..8bb9112 --- /dev/null +++ b/roles/aten_pdu/tasks/main.yml @@ -0,0 +1,31 @@ +--- +- name: Install packages + ansible.builtin.package: + name: "{{ item }}" + state: installed + with_items: + - mosquitto + - net-snmp-utils + +# https://www.aten.com/eu/en/products/power-distribution-&-racks/rack-pdu/pe8108/ +- name: Install custom mib + ansible.builtin.copy: + dest: /usr/share/snmp/mibs/ATEN-PE-CFG.txt + src: ATEN-PE-CFG_str_1.3.128.mib + mode: "0644" + owner: root + group: "{{ ansible_wheel }}" + +- name: Install mqtt publish script + ansible.builtin.copy: + dest: /usr/local/bin/aten-mqtt-publish + src: aten-mqtt-publish.sh + mode: "0755" + owner: root + group: "{{ ansible_wheel }}" + +- name: Add mqtt publish cron job + ansible.builtin.cron: + name: aten-mqtt-publish + job: /usr/local/bin/aten-mqtt-publish + minute: "*/5" diff --git a/roles/audiobookshelf/files/audiobookshelf.default b/roles/audiobookshelf/files/audiobookshelf.default new file mode 100644 index 0000000..4b553f5 --- /dev/null +++ b/roles/audiobookshelf/files/audiobookshelf.default @@ -0,0 +1,4 @@ +METADATA_PATH=/srv/audiobookshelf/metadata +CONFIG_PATH=/srv/audiobookshelf/config +PORT=13378 +HOST=127.0.0.1 diff --git a/roles/audiobookshelf/files/meta.md b/roles/audiobookshelf/files/meta.md new file mode 100644 index 0000000..5e22e02 --- /dev/null +++ b/roles/audiobookshelf/files/meta.md @@ -0,0 +1,30 @@ += Preparing files for upload = + +== Filenames == + +Filenames should always contain track number (and optionally disc number) with leading zeros first and subtitle after that. Few exmaples: + +``` +01. Luku.mp3 +01. Osa.mp3 +CD 1 - 01.mp3 +``` + +Directory should also contain `cover.jpg` with book cover picture and `desc.txt` containing book description. + +== Metadata (id3 tags) == + +First clear old tags then set new ones: + +``` +id3v2 -D "01. Osa.mp3" +id3v2 \ + --TPE1 "Douglas Adams" \ + --TALB "$(echo 'Linnunradan käsikirja liftareille' | iconv -f utf-8 -t iso-8859-1)" \ + --TCOM "$(echo 'Heikki Kinnunen,Pekka Autiovuori,Yrjö Järvinen,Martti Järvinen,Esa Saario,Kauko Helavirta,Aila Svedberg' | iconv -f utf-8 -t iso-8859-1)" \ + --TLAN "fi" \ + --TPUB "Yleisradio" \ + --TYER 1984 \ + --genre "Science Fiction/Fiction/Humor" \ + "01. Osa.mp3" +``` diff --git a/roles/audiobookshelf/handlers/main.yml b/roles/audiobookshelf/handlers/main.yml new file mode 100644 index 0000000..fd2df00 --- /dev/null +++ b/roles/audiobookshelf/handlers/main.yml @@ -0,0 +1,5 @@ +--- +- name: Restart audiobookshelf + ansible.builtin.service: + name: audiobookshelf + state: restarted diff --git a/roles/audiobookshelf/meta/main.yml b/roles/audiobookshelf/meta/main.yml new file mode 100644 index 0000000..954fabd --- /dev/null +++ b/roles/audiobookshelf/meta/main.yml @@ -0,0 +1,3 @@ +--- +dependencies: + - {role: nginx} diff --git a/roles/audiobookshelf/tasks/main.yml b/roles/audiobookshelf/tasks/main.yml new file mode 100644 index 0000000..1bc2f99 --- /dev/null +++ b/roles/audiobookshelf/tasks/main.yml @@ -0,0 +1,90 @@ +--- +- name: Enable repository + ansible.builtin.yum_repository: + name: audiobookshelf + baseurl: https://raw.githubusercontent.com/lkiesow/audiobookshelf-rpm/el$releasever/ + description: Audiobookshelf el$releasever repository + gpgcheck: true + gpgkey: https://raw.githubusercontent.com/lkiesow/audiobookshelf-rpm/main/audiobookshelf-rpm.key + enabled: true + +- name: Install packcages + ansible.builtin.package: + name: audiobookshelf + state: present + +- name: Create data directories + ansible.builtin.file: + path: "{{ item }}" + state: directory + mode: "0770" + owner: root + group: audiobookshelf + with_items: + - /export/audiobookshelf + - /export/audiobookshelf/audiobooks + - /export/audiobookshelf/config + - /export/audiobookshelf/metadata + - /export/audiobookshelf/podcasts + - /export/audiobookshelf/radioplays + +- name: Link data directory + ansible.builtin.file: + dest: /srv/audiobookshelf + src: /export/audiobookshelf + state: link + owner: root + group: "{{ ansible_wheel }}" + follow: false + +- name: Copy naming instructions + ansible.builtin.copy: + dest: /srv/audiobookshelf/audiobooks/README.md + src: meta.md + mode: "0644" + owner: root + group: "{{ ansible_wheel }}" + +- name: Copy service config + ansible.builtin.copy: + dest: /etc/default/audiobookshelf + src: audiobookshelf.default + mode: "0644" + owner: root + group: "{{ ansible_wheel }}" + notify: Restart audiobookshelf + +- name: Enable service + ansible.builtin.service: + name: audiobookshelf + state: started + enabled: true + +- name: Allow nginx to connect audiobookshelf + ansible.posix.seboolean: + name: httpd_can_network_connect + state: true + persistent: true + +- name: Copy nginx config + ansible.builtin.copy: + dest: "/etc/nginx/conf.d/{{ inventory_hostname }}/audiobookshelf.conf" + content: | + location / { + proxy_set_header Connection $connection_upgrade; + proxy_set_header Host audiobooks.foo.sh; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_http_version 1.1; + proxy_pass http://127.0.0.1:13378/; + location /audiobookshelf/api/upload { + # increase size to allow uploads + client_max_body_size 10g; + proxy_pass http://127.0.0.1:13378/api/upload; + } + } + mode: "0644" + owner: root + group: "{{ ansible_wheel }}" + notify: Restart nginx diff --git a/roles/authcheck/tasks/main.yml b/roles/authcheck/tasks/main.yml index 222d5b4..8ca80cf 100644 --- a/roles/authcheck/tasks/main.yml +++ b/roles/authcheck/tasks/main.yml @@ -10,11 +10,19 @@ group: authcheck shell: /sbin/nologin +- name: Enable user lingering + ansible.builtin.command: + argv: + - loginctl + - enable-linger + - authcheck + creates: /var/lib/systemd/linger/authcheck + - name: Get container source ansible.builtin.git: dest: /usr/local/src/docker-authcheck repo: https://github.com/foo-sh/docker-authcheck.git - update: false + update: true version: main notify: Rebuild authcheck-container @@ -22,7 +30,7 @@ ansible.builtin.template: dest: /etc/systemd/system/authcheck-container.service src: authcheck-container.service.j2 - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" @@ -39,7 +47,7 @@ location /authcheck { proxy_pass http://127.0.0.1:8003/; } - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" notify: Restart nginx diff --git a/roles/autofs/defaults/main.yml b/roles/autofs/defaults/main.yml new file mode 100644 index 0000000..404004a --- /dev/null +++ b/roles/autofs/defaults/main.yml @@ -0,0 +1,3 @@ +--- +autofs_home: true +autofs_roles: true diff --git a/roles/autofs/tasks/main.yml b/roles/autofs/tasks/main.yml index d3a3121..19f9565 100644 --- a/roles/autofs/tasks/main.yml +++ b/roles/autofs/tasks/main.yml @@ -34,7 +34,7 @@ ansible.builtin.template: dest: /etc/autofs_ldap_auth.conf src: autofs_ldap_auth.conf.j2 - mode: 0600 + mode: "0600" owner: root group: "{{ ansible_wheel }}" notify: Restart autofs @@ -43,7 +43,7 @@ ansible.builtin.template: dest: /etc/auto.master src: auto.master.j2 - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" notify: Restart autofs @@ -74,7 +74,7 @@ ansible.builtin.copy: dest: "/etc/profile.d/{{ item }}" src: "{{ item }}" - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" with_items: diff --git a/roles/autofs/templates/auto.master.j2 b/roles/autofs/templates/auto.master.j2 index ee9e28f..4087487 100644 --- a/roles/autofs/templates/auto.master.j2 +++ b/roles/autofs/templates/auto.master.j2 @@ -1,2 +1,6 @@ -/home ldap:///ou=People,{{ ldap_basedn }} rw,nosuid,nodev,rsize=1048576,wsize=1048576 -/roles ldap:///ou=Groups,{{ ldap_basedn }} rw,nosuid,nodev,rsize=1048576,wsize=1048576 --ghost +{% if autofs_home %} +/home ldap:///ou=People,{{ ldap_basedn }} rw,noatime,nosuid,nodev,rsize=1048576,wsize=1048576,xprtsec=mtls +{% endif %} +{% if autofs_roles %} +/roles ldap:///ou=Groups,{{ ldap_basedn }} rw,noatime,nosuid,nodev,rsize=1048576,wsize=1048576,xprtsec=mtls --ghost +{% endif %} diff --git a/roles/backup_base/defaults/main.yml b/roles/backup_base/defaults/main.yml new file mode 100644 index 0000000..2a14dc3 --- /dev/null +++ b/roles/backup_base/defaults/main.yml @@ -0,0 +1,3 @@ +--- +backup_datadir: >- + {% if ansible_local['export'] %}/export{% else %}/srv{% endif %}/backup diff --git a/roles/backup_base/tasks/main.yml b/roles/backup_base/tasks/main.yml new file mode 100644 index 0000000..cb10097 --- /dev/null +++ b/roles/backup_base/tasks/main.yml @@ -0,0 +1,55 @@ +--- +- name: Create backup group + ansible.builtin.group: + name: backup + gid: 306 + +- name: Create backup user + ansible.builtin.user: + name: backup + comment: Backup Service + createhome: false + group: backup + home: /var/empty + shell: /bin/sh + uid: 306 + +- name: Create backup directory + ansible.builtin.file: + path: "{{ backup_datadir }}" + state: directory + mode: "0750" + owner: root + group: backup + +- name: Link backup directory + ansible.builtin.file: + dest: /srv/backup + src: "{{ backup_datadir }}" + state: link + owner: root + group: "{{ ansible_wheel }}" + follow: false + when: backup_datadir != "/srv/backup" + +- name: Create authorized_keys + ansible.builtin.copy: + dest: /etc/ssh/authorized_keys.backup + src: ../files/ssh/backup.pub + mode: "0640" + owner: root + group: backup + when: "'sftpbackup' in group_names" + +- name: Configure sshd chroot + ansible.builtin.blockinfile: + path: /etc/ssh/sshd_config + block: | + Match User backup + ChrootDirectory /srv/backup + ForceCommand internal-sftp + AuthorizedKeysFile /etc/ssh/authorized_keys.backup + marker: "# {mark} ANSIBLE MANAGED BLOCK (user backup)" + validate: "sshd -t -f %s" + when: "'sftpbackup' in group_names" + notify: Restart sshd diff --git a/roles/backup_bitbucket/files/backup-bitbucket.sh b/roles/backup_bitbucket/files/backup-bitbucket.sh new file mode 100644 index 0000000..a97097e --- /dev/null +++ b/roles/backup_bitbucket/files/backup-bitbucket.sh @@ -0,0 +1,24 @@ +#!/bin/sh + +USERS="tmakinen" + +set -eu +umask 027 + +cd /srv/backup/bitbucket.org + +for _user in $USERS ; do + curl -sSf "https://api.bitbucket.org/2.0/repositories/${_user}" | \ + jq -r '.values | .[] | [.name, .scm] | @tsv' | \ + while read -r _repo _scm + do + [ "$_scm" = "git" ] || continue + _url="https://bitbucket.org/${_user}/${_repo}" + _gitdir="${_user}/${_repo}" + if [ ! -d "$_gitdir" ]; then + mkdir -p "$_gitdir" + git --git-dir="$_gitdir" init --quiet --bare + fi + git --git-dir="$_gitdir" fetch --quiet --force --prune --tags "$_url" "refs/heads/*:refs/heads/*" + done +done diff --git a/roles/backup_bitbucket/meta/main.yml b/roles/backup_bitbucket/meta/main.yml new file mode 100644 index 0000000..f178512 --- /dev/null +++ b/roles/backup_bitbucket/meta/main.yml @@ -0,0 +1,3 @@ +--- +dependencies: + - {role: backup_base} diff --git a/roles/backup_bitbucket/tasks/main.yml b/roles/backup_bitbucket/tasks/main.yml new file mode 100644 index 0000000..d41605a --- /dev/null +++ b/roles/backup_bitbucket/tasks/main.yml @@ -0,0 +1,32 @@ +--- +- name: Install dependencies + ansible.builtin.package: + name: "{{ item }}" + state: installed + with_items: + - git + - jq + +- name: Create backup directory + ansible.builtin.file: + path: /srv/backup/bitbucket.org + state: directory + mode: "0770" + owner: root + group: backup + +- name: Copy backup script + ansible.builtin.copy: + dest: /usr/local/sbin/backup-bitbucket + src: backup-bitbucket.sh + mode: "0755" + owner: root + group: "{{ ansible_wheel }}" + +- name: Add cron job + ansible.builtin.cron: + name: bitbucket-backup + job: /usr/local/sbin/backup-bitbucket + hour: "03" + minute: "10" + user: backup diff --git a/roles/backup_github/files/backup-github.sh b/roles/backup_github/files/backup-github.sh new file mode 100755 index 0000000..6d2c598 --- /dev/null +++ b/roles/backup_github/files/backup-github.sh @@ -0,0 +1,22 @@ +#!/bin/sh + +ORGS="foo-sh" + +set -eu +umask 027 + +cd /srv/backup/github.com + +for _org in $ORGS ; do + curl -sSf "https://api.github.com/orgs/foo-sh/repos" | jq -r '.[] | .name' | \ + while read -r _repo + do + _url="https://github.com/${_org}/${_repo}.git" + _gitdir="${_org}/${_repo}" + if [ ! -d "$_gitdir" ]; then + mkdir -p "$_gitdir" + git --git-dir="$_gitdir" init --quiet --bare + fi + git --git-dir="$_gitdir" fetch --quiet --force --prune --tags "$_url" "refs/heads/*:refs/heads/*" + done +done diff --git a/roles/backup_github/meta/main.yml b/roles/backup_github/meta/main.yml new file mode 100644 index 0000000..f178512 --- /dev/null +++ b/roles/backup_github/meta/main.yml @@ -0,0 +1,3 @@ +--- +dependencies: + - {role: backup_base} diff --git a/roles/backup_github/tasks/main.yml b/roles/backup_github/tasks/main.yml new file mode 100644 index 0000000..6d6ffdc --- /dev/null +++ b/roles/backup_github/tasks/main.yml @@ -0,0 +1,32 @@ +--- +- name: Install dependencies + ansible.builtin.package: + name: "{{ item }}" + state: installed + with_items: + - git + - jq + +- name: Create backup directory + ansible.builtin.file: + path: /srv/backup/github.com + state: directory + mode: "0770" + owner: root + group: backup + +- name: Copy backup script + ansible.builtin.copy: + dest: /usr/local/sbin/backup-github + src: backup-github.sh + mode: "0755" + owner: root + group: "{{ ansible_wheel }}" + +- name: Add cron job + ansible.builtin.cron: + name: github-backup + job: /usr/local/sbin/backup-github + hour: "03" + minute: "20" + user: backup diff --git a/roles/backup_server/files/backup-bitbucket.py b/roles/backup_server/files/backup-bitbucket.py deleted file mode 100644 index 15cb651..0000000 --- a/roles/backup_server/files/backup-bitbucket.py +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/bin/env python3 - -import os -import json -from subprocess import call -from urllib.request import urlopen - -USERS = ["tmakinen"] -BACKUPDIR = "/srv/backup/bitbucket.org" - - -def repolist(username): - f = urlopen(f"https://api.bitbucket.org/2.0/repositories/{username}") - data = json.load(f) - f.close() - - for repo in data["values"]: - yield ( - { - "name": repo["name"], - "scm": repo["scm"], - "wiki": repo["has_wiki"], - "issues": repo["has_issues"], - } - ) - - -def gitbackup(destination, repo): - if not os.path.exists(destination): - os.makedirs(destination) - call(["git", "clone", "--quiet", repo, destination]) - else: - os.chdir(destination) - call(["git", f"--git-dir={destination}/.git", "pull", "--quiet"]) - - -if __name__ == "__main__": - for user in USERS: - for repo in repolist(user): - if repo["scm"] == "git": - gitbackup( - f"{BACKUPDIR}/{user}/{repo['name']}", - f"https://bitbucket.org/{user}/{repo['name']}.git", - ) - if repo["wiki"]: - gitbackup( - f"{BACKUPDIR}/{user}/{repo['name']}-wiki", - f"https://bitbucket.org/{user}/{repo['name']}.git/wiki", - ) - else: - raise NotImplementedError("{repo['scm']} repositories not supported") diff --git a/roles/backup_server/tasks/main.yml b/roles/backup_server/tasks/main.yml deleted file mode 100644 index 8577419..0000000 --- a/roles/backup_server/tasks/main.yml +++ /dev/null @@ -1,64 +0,0 @@ ---- -- name: Install packages - ansible.builtin.package: - name: "{{ item }}" - state: installed - with_items: - - git - - rclone - -- name: Create backup group - ansible.builtin.group: - name: backup - gid: 1005 - -- name: Create backup user - ansible.builtin.user: - name: backup - comment: Backup Service - createhome: false - group: backup - home: /var/empty - shell: /bin/sh - uid: 1005 - -- name: Create backup directory - ansible.builtin.file: - path: /export/backup - state: directory - mode: 0755 - owner: root - group: "{{ ansible_wheel }}" - -- name: Link backup directory - ansible.builtin.file: - dest: /srv/backup - src: /export/backup - state: link - owner: root - group: "{{ ansible_wheel }}" - follow: false - -- name: Create Bitbucket backup directory - ansible.builtin.file: - path: /export/backup/bitbucket.org - state: directory - mode: 0775 - owner: root - group: backup - -- name: Install Bitbucket backup script - ansible.builtin.copy: - dest: /usr/local/sbin/backup-bitbucket - src: backup-bitbucket.py - mode: 0755 - owner: root - group: "{{ ansible_wheel }}" - -- name: Add Bitbucket backup cron job - ansible.builtin.cron: - name: bitbucket-backup - job: /usr/local/sbin/backup-bitbucket - hour: "03" - minute: "10" - user: backup diff --git a/roles/base/files/export.fact.sh b/roles/base/files/export.fact.sh new file mode 100755 index 0000000..1f3075e --- /dev/null +++ b/roles/base/files/export.fact.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +set -eu + +if mount | grep -qE "on /export" ; then + echo "true" +else + echo "false" +fi diff --git a/roles/base/tasks/OpenBSD.yml b/roles/base/tasks/OpenBSD.yml index d925bf6..b8ca184 100644 --- a/roles/base/tasks/OpenBSD.yml +++ b/roles/base/tasks/OpenBSD.yml @@ -3,7 +3,7 @@ ansible.builtin.copy: dest: /etc/myname content: "{{ inventory_hostname }}\n" - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" @@ -11,7 +11,7 @@ ansible.builtin.copy: dest: /etc/installurl content: "https://mirrors.foo.sh/openbsd/\n" - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" when: ansible_datacenter == "home" @@ -30,7 +30,7 @@ ansible.builtin.copy: dest: "{{ item }}" content: "VERBOSESTATUS=0\n" - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" with_items: @@ -53,7 +53,7 @@ ansible.builtin.file: name: /srv state: directory - mode: 0755 + mode: "0755" owner: root group: "{{ ansible_wheel }}" @@ -64,5 +64,6 @@ - opensmtpd - pf - syslogd + - unwind loop_control: loop_var: role diff --git a/roles/base/tasks/RedHat.yml b/roles/base/tasks/RedHat.yml index 8e6ca6e..0e477a1 100644 --- a/roles/base/tasks/RedHat.yml +++ b/roles/base/tasks/RedHat.yml @@ -3,6 +3,31 @@ ansible.builtin.hostname: name: "{{ inventory_hostname }}" +- name: Check if dnf python bindings are installed + ansible.builtin.command: + argv: + - rpm + - "-q" + - python3-dnf + register: result + failed_when: false + changed_when: false + +- name: Install dnf python bindings + ansible.builtin.command: + argv: + - dnf + - install + - "-y" + - python3-dnf + when: result.rc != 0 + +- name: Install OS specific roles for physical hardware + ansible.builtin.include_role: + name: cpupower + when: + - ansible_virtualization_role == "host" + - name: Install OS specific roles ansible.builtin.include_role: name: "{{ role }}" @@ -12,6 +37,11 @@ loop_control: loop_var: role +- name: Install systemd-resolved + ansible.builtin.include_role: + name: systemd_resolved + when: ansible_distribution == "Fedora" + - name: Install firewall ansible.builtin.include_role: name: iptables @@ -81,17 +111,24 @@ - vim-enhanced # working vi :) - xterm # resize +- name: Install roles for physical hardware + ansible.builtin.include_role: + name: fwupd + when: + - ansible_virtualization_role == "host" + - name: Install packages for physical hardware ansible.builtin.package: name: "{{ item }}" state: installed with_items: + - hdparm - pciutils - powertop when: - ansible_virtualization_role == "host" -- name: Install el7/el8 packages +- name: Install packages (el8 and older) ansible.builtin.package: name: "{{ item }}" state: installed @@ -99,7 +136,7 @@ - mailx when: ansible_distribution_major_version|int <= 8 -- name: Install el9 packages +- name: Install packages (el9 and newer) ansible.builtin.package: name: "{{ item }}" state: installed @@ -112,18 +149,39 @@ dest: /etc/GREP_COLORS state: absent +- name: Check date format + ansible.builtin.shell: + cmd: | + set -o pipefail + localectl status | grep -E '^\s+LC_TIME=C.UTF-8$' + executable: /bin/bash + register: locale_check + changed_when: false + failed_when: false + check_mode: false + +- name: Set date format to use 24 hour clock + ansible.builtin.command: + argv: + - localectl + - set-locale + - LC_TIME=C.UTF-8 + register: result + changed_when: result.rc == 0 + when: locale_check.rc != 0 + - name: Store date and time for bash history ansible.builtin.copy: dest: /etc/profile.d/history.sh content: 'export HISTTIMEFORMAT="%Y-%m-%d %H:%M:%S "' - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" -- name: Cron job for downloading yum updates +- name: Cron job for downloading updates ansible.builtin.cron: - name: yum-downloadonly + name: dnf-downloadonly user: root hour: "3" minute: "{{ 59 | random(seed=inventory_hostname) }}" - job: "yum -d 0 -e 0 -y --downloadonly update > /dev/null" + job: "dnf-3 -q -y update --downloadonly" diff --git a/roles/base/tasks/main.yml b/roles/base/tasks/main.yml index 5281333..cf661ed 100644 --- a/roles/base/tasks/main.yml +++ b/roles/base/tasks/main.yml @@ -1,8 +1,28 @@ --- +- name: Group by domainname + ansible.builtin.group_by: + key: "{{ inventory_hostname.split('.')[1] }}" + changed_when: false + when: inventory_hostname | split('.') | length == 4 + +- name: Get ansible server name + ansible.builtin.command: + argv: + - hostname + - -f + changed_when: false + delegate_to: localhost + register: result + +- name: Store ansible server name + ansible.builtin.set_fact: + ansible_server: "{{ result.stdout }}" + cacheable: false + - name: Setup ansible custom facts ansible.builtin.file: dest: "{{ item }}" - mode: 0755 + mode: "0755" owner: root group: "{{ ansible_wheel }}" state: directory @@ -13,14 +33,8 @@ - name: Add ansible_export fact ansible.builtin.copy: dest: /etc/ansible/facts.d/export.fact - content: | - #!/bin/sh - if [ -d /export ]; then - echo "true" - else - echo "false" - fi - mode: 0755 + src: export.fact.sh + mode: "0755" owner: root group: "{{ ansible_wheel }}" @@ -36,7 +50,7 @@ ansible.builtin.copy: content: "\n" dest: "/etc/at.allow" - mode: 0600 + mode: "0600" owner: root group: "{{ ansible_wheel }}" @@ -48,6 +62,8 @@ - pki - psacct - sshd + - sshd_cert + - node_exporter loop_control: loop_var: role diff --git a/roles/blackbox_exporter/files/blackbox.yml b/roles/blackbox_exporter/files/blackbox.yml new file mode 100644 index 0000000..9152489 --- /dev/null +++ b/roles/blackbox_exporter/files/blackbox.yml @@ -0,0 +1,17 @@ +--- +modules: + http: + prober: http + http: + valid_status_codes: + - 200 + - 401 + - 403 + ssh: + prober: tcp + tcp: + query_response: + - expect: "^SSH-2.0-" + - send: "SSH-2.0-blackbox-ssh-check" + tcp: + prober: tcp diff --git a/roles/blackbox_exporter/handlers/main.yml b/roles/blackbox_exporter/handlers/main.yml new file mode 100644 index 0000000..34e0f2d --- /dev/null +++ b/roles/blackbox_exporter/handlers/main.yml @@ -0,0 +1,5 @@ +--- +- name: Restart blackbox_exporter + ansible.builtin.service: + name: blackbox_exporter + state: restarted diff --git a/roles/blackbox_exporter/tasks/main.yml b/roles/blackbox_exporter/tasks/main.yml new file mode 100644 index 0000000..ade2edd --- /dev/null +++ b/roles/blackbox_exporter/tasks/main.yml @@ -0,0 +1,40 @@ +--- +- name: Install packages + ansible.builtin.package: + name: blackbox_exporter + state: installed + +- name: Add user to hostkey group + ansible.builtin.user: + name: _blackboxexporter + groups: hostkey + append: true + create_home: false + notify: Restart blackbox_exporter + +- name: Create main config + ansible.builtin.copy: + dest: /etc/blackbox_exporter/blackbox.yml + src: blackbox.yml + mode: "0644" + owner: root + group: "{{ ansible_wheel }}" + notify: Restart blackbox_exporter + +- name: Create web-config + ansible.builtin.template: + dest: /etc/blackbox_exporter/web-config.yml + src: web-config.yml.j2 + mode: "0644" + owner: root + group: "{{ ansible_wheel }}" + notify: Restart blackbox_exporter + +- name: Enable service + ansible.builtin.service: + name: blackbox_exporter + state: started + arguments: > + --config.file=/etc/blackbox_exporter/blackbox.yml + --web.config.file=/etc/blackbox_exporter/web-config.yml + enabled: true diff --git a/roles/blackbox_exporter/templates/web-config.yml.j2 b/roles/blackbox_exporter/templates/web-config.yml.j2 new file mode 100644 index 0000000..03e5466 --- /dev/null +++ b/roles/blackbox_exporter/templates/web-config.yml.j2 @@ -0,0 +1,11 @@ +--- +tls_server_config: + key_file: {{ tls_private }}/{{ inventory_hostname }}.key + cert_file: {{ tls_certs }}/{{ inventory_hostname }}.crt + client_ca_file: {{ tls_certs }}/ca.crt + client_auth_type: RequireAndVerifyClientCert + client_allowed_sans: +{% for host in groups['prometheus'] %} + - {{ host }} +{% endfor %} + min_version: TLS13 diff --git a/roles/certbot/meta/main.yml b/roles/certbot/meta/main.yml index b95ceec..954fabd 100644 --- a/roles/certbot/meta/main.yml +++ b/roles/certbot/meta/main.yml @@ -1,3 +1,3 @@ --- dependencies: - - {role: nginx/server} + - {role: nginx} diff --git a/roles/certbot/tasks/main.yml b/roles/certbot/tasks/main.yml index 1d22823..189b36b 100644 --- a/roles/certbot/tasks/main.yml +++ b/roles/certbot/tasks/main.yml @@ -7,7 +7,7 @@ - name: Create certbot group ansible.builtin.group: name: certbot - gid: 1002 + gid: 307 - name: Create certbot user ansible.builtin.user: @@ -17,20 +17,20 @@ group: certbot home: /var/empty shell: /sbin/nologin - uid: 1002 + uid: 307 - name: Add certbot nginx site ansible.builtin.include_role: - name: nginx/site + name: nginx_site vars: - site: certbot.home.foo.sh + nginx_site_name: certbot.home.foo.sh - name: Create certbot .well-known directory ansible.builtin.file: path: /srv/web/certbot.home.foo.sh/.well-known owner: root group: "{{ ansible_wheel }}" - mode: 0755 + mode: "0755" state: directory - name: Create certbot directories @@ -38,7 +38,7 @@ path: "{{ item }}" owner: root group: certbot - mode: 0775 + mode: "0775" state: directory with_items: - /srv/web/certbot.home.foo.sh/.well-known/acme-challenge @@ -57,7 +57,7 @@ ansible.builtin.copy: dest: /etc/letsencrypt/cli.ini src: cli.ini - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" diff --git a/roles/clamav/tasks/main.yml b/roles/clamav/tasks/main.yml index 469e46a..bbd796a 100644 --- a/roles/clamav/tasks/main.yml +++ b/roles/clamav/tasks/main.yml @@ -12,7 +12,7 @@ ansible.builtin.copy: dest: /etc/tmpfiles.d/clamd.scan.conf content: "d /run/clamd.scan 711 clamscan clamscan" - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" notify: Refresh clamd socket directory diff --git a/roles/collab/tasks/main.yml b/roles/collab/tasks/main.yml index 95c1446..b3df48d 100644 --- a/roles/collab/tasks/main.yml +++ b/roles/collab/tasks/main.yml @@ -2,7 +2,7 @@ - name: Add graphviz repository ansible.builtin.yum_repository: name: graphviz - baseurl: > + baseurl: >- {{ "https://www2.graphviz.org" + "/Packages/stable/centos/$releasever/os/$basearch/" @@ -27,7 +27,7 @@ ansible.builtin.get_url: url: "https://static.moinmo.in/files/moin-{{ moin_version }}.tar.gz" dest: "{{ srcdir }}" - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" checksum: sha1:3eb13b4730bd97259a41c4cd500f8433778ff8cf @@ -57,7 +57,7 @@ ansible.builtin.copy: src: foosh.py dest: "{{ srcdir }}/collabbackend/collabbackend/plugin/theme/foosh.py" - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" @@ -99,13 +99,13 @@ - name: Create group collab ansible.builtin.group: name: collab - gid: 1003 + gid: 310 - name: Create user collab ansible.builtin.user: name: collab comment: Service Collab - uid: 1003 + uid: 310 group: collab home: /var/lib/collab shell: /sbin/nologin @@ -114,14 +114,14 @@ ansible.builtin.copy: content: "umask 077\n" dest: /var/lib/collab/.profile - mode: 0440 + mode: "0440" owner: collab group: collab - name: Create config directories ansible.builtin.file: path: "{{ item }}" - mode: 0755 + mode: "0755" owner: root group: "{{ ansible_wheel }}" state: directory @@ -133,7 +133,7 @@ ansible.builtin.copy: src: collab.ini dest: /etc/local/collab/collab.ini - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" @@ -145,7 +145,7 @@ - name: Create data directory ansible.builtin.file: path: /export/wikis - mode: 0755 + mode: "0755" owner: root group: root seuser: _default @@ -162,7 +162,7 @@ ansible.builtin.file: path: /srv/wikis/collab state: directory - mode: 0750 + mode: "0750" owner: root group: collab @@ -170,7 +170,7 @@ ansible.builtin.file: state: directory path: "{{ item }}" - mode: 02770 + mode: "02770" owner: collab group: collab with_items: @@ -196,7 +196,7 @@ ansible.builtin.copy: src: collab-htaccess dest: collab-htaccess - mode: 0660 + mode: "0660" owner: collab group: collab @@ -204,7 +204,7 @@ ansible.builtin.copy: src: "{{ srcdir }}/collabbackend/config/{{ item }}" dest: /srv/wikis/collab/config/{{ item }} - mode: 0660 + mode: "0660" owner: collab group: collab seuser: _default @@ -220,7 +220,7 @@ ansible.builtin.copy: src: "{{ srcdir }}/collabbackend/packages/CollabBase.zip" dest: /var/lib/collab/CollabBase.zip - mode: 0660 + mode: "0660" owner: collab group: collab remote_src: true @@ -265,21 +265,7 @@ ansible.builtin.template: src: collab.conf.j2 dest: /etc/httpd/conf.local.d/collab.conf - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" notify: Restart apache - -- name: Import sftpuser role - ansible.builtin.import_role: - name: sftpuser - vars: - chroot: /srv/wikis/collab - user: backup - publickeys: "{{ backup_publickeys }}" - -- name: Add backup user to collab group - ansible.builtin.user: - name: backup - groups: collab - append: true diff --git a/roles/cpupower/files/cpupower.sysconfig b/roles/cpupower/files/cpupower.sysconfig new file mode 100644 index 0000000..a75fd87 --- /dev/null +++ b/roles/cpupower/files/cpupower.sysconfig @@ -0,0 +1,3 @@ +# See 'cpupower help' and cpupower(1) for more info +CPUPOWER_START_OPTS="frequency-set -g ondemand" +CPUPOWER_STOP_OPTS="frequency-set -g performance" diff --git a/roles/gitea_runner/handlers/main.yml b/roles/cpupower/handlers/main.yml similarity index 52% rename from roles/gitea_runner/handlers/main.yml rename to roles/cpupower/handlers/main.yml index 3f4dbfd..c37fd46 100644 --- a/roles/gitea_runner/handlers/main.yml +++ b/roles/cpupower/handlers/main.yml @@ -1,5 +1,5 @@ --- -- name: Restart act_runner +- name: Restart cpupower ansible.builtin.service: - name: act_runner + name: cpupower state: restarted diff --git a/roles/cpupower/tasks/main.yml b/roles/cpupower/tasks/main.yml new file mode 100644 index 0000000..4cd1f83 --- /dev/null +++ b/roles/cpupower/tasks/main.yml @@ -0,0 +1,15 @@ +--- +- name: Copy config + ansible.builtin.copy: + dest: /etc/sysconfig/cpupower + src: cpupower.sysconfig + mode: "0644" + owner: root + group: "{{ ansible_wheel }}" + notify: Restart cpupower + +- name: Enable service + ansible.builtin.service: + name: cpupower + state: started + enabled: true diff --git a/roles/cups_server/files/cups-ppd/Samsung_ML-3051ND.ppd b/roles/cups_server/files/cups-ppd/Samsung_ML-3051ND.ppd new file mode 100644 index 0000000..2e13ae2 --- /dev/null +++ b/roles/cups_server/files/cups-ppd/Samsung_ML-3051ND.ppd @@ -0,0 +1,219 @@ +*PPD-Adobe: "4.3" +*% +*% For information on using this, and to obtain the required backend +*% script, consult http://www.openprinting.org/ +*% +*% This file is published under the GNU General Public License +*% +*% PPD-O-MATIC (4.0.0 or newer) generated this PPD file. It is for use with +*% all programs and environments which use PPD files for dealing with +*% printer capability information. The printer must be configured with the +*% "foomatic-rip" backend filter script of Foomatic 4.0.0 or newer. This +*% file and "foomatic-rip" work together to support PPD-controlled printer +*% driver option access with all supported printer drivers and printing +*% spoolers. +*% +*% To save this file on your disk, wait until the download has completed +*% (the animation of the browser logo must stop) and then use the +*% "Save as..." command in the "File" menu of your browser or in the +*% pop-up manu when you click on this document with the right mouse button. +*% DO NOT cut and paste this file into an editor with your mouse. This can +*% introduce additional line breaks which lead to unexpected results. +*% +*% You may save this file as 'Samsung-ML-3051ND-Postscript.ppd' +*% +*% +*FormatVersion: "4.3" +*FileVersion: "1.1" +*LanguageVersion: English +*LanguageEncoding: ISOLatin1 +*PCFileName: "POSTSCRI.PPD" +*Manufacturer: "Samsung" +*Product: "(ML-3051ND)" +*cupsVersion: 1.0 +*cupsManualCopies: True +*cupsModelNumber: 2 +*cupsFilter: "application/vnd.cups-postscript 100 foomatic-rip" +*cupsFilter: "application/vnd.cups-pdf 0 foomatic-rip" +*%pprRIP: foomatic-rip other +*ModelName: "Samsung ML-3051ND" +*ShortNickName: "Samsung ML-3051ND Postscript" +*NickName: "Samsung ML-3051ND Foomatic/Postscript (recommended)" +*PSVersion: "(3010.000) 550" +*PSVersion: "(3010.000) 651" +*PSVersion: "(3010.000) 652" +*PSVersion: "(3010.000) 653" +*PSVersion: "(3010.000) 704" +*PSVersion: "(3010.000) 705" +*PSVersion: "(3010.000) 800" +*PSVersion: "(3010.000) 815" +*PSVersion: "(3010.000) 850" +*PSVersion: "(3010.000) 860" +*PSVersion: "(3010.000) 861" +*PSVersion: "(3010.000) 862" +*PSVersion: "(3010.000) 863" +*PSVersion: "(3010.000) 864" +*PSVersion: "(3010.000) 870" +*LanguageLevel: "3" +*ColorDevice: False +*DefaultColorSpace: Gray +*FileSystem: False +*Throughput: "1" +*LandscapeOrientation: Plus90 +*TTRasterizer: Type42 +*1284DeviceID: "MFG:Samsung;MDL:ML-3051ND;DRV:DPostscript,R1,M0,TP;" + +*driverName Postscript: "" +*driverType P/PostScript: "" +*driverUrl: "http://partners.adobe.com/public/developer/ps/index_specs.html" +*driverObsolete: False +*driverManufacturerSupplied: False + + + + +*HWMargins: 18 36 18 36 +*VariablePaperSize: True +*MaxMediaWidth: 100000 +*MaxMediaHeight: 100000 +*NonUIOrderDependency: 100 AnySetup *CustomPageSize +*CustomPageSize True: "pop pop pop +<>setpagedevice" +*End +*ParamCustomPageSize Width: 1 points 36 100000 +*ParamCustomPageSize Height: 2 points 36 100000 +*ParamCustomPageSize Orientation: 3 int 0 0 +*ParamCustomPageSize WidthOffset: 4 points 0 0 +*ParamCustomPageSize HeightOffset: 5 points 0 0 + +*FoomaticIDs: Samsung-ML-3051ND Postscript +*FoomaticRIPCommandLine: "cat%A%B%Z" +*FoomaticRIPNoPageAccounting: True + +*OpenGroup: General/General + +*OpenUI *PageSize/Page Size: PickOne +*OrderDependency: 100 AnySetup *PageSize +*DefaultPageSize: Letter +*PageSize Letter/US Letter: "<>setpagedevice" +*PageSize A4/A4: "<>setpagedevice" +*PageSize 11x17/11x17: "<>setpagedevice" +*PageSize A3/A3: "<>setpagedevice" +*PageSize A5/A5: "<>setpagedevice" +*PageSize B5/B5 (JIS): "<>setpagedevice" +*PageSize Env10/Envelope #10: "<>setpagedevice" +*PageSize EnvC5/Envelope C5: "<>setpagedevice" +*PageSize EnvDL/Envelope DL: "<>setpagedevice" +*PageSize EnvISOB5/Envelope B5: "<>setpagedevice" +*PageSize EnvMonarch/Envelope Monarch: "<>setpagedevice" +*PageSize Executive/Executive: "<>setpagedevice" +*PageSize Legal/US Legal: "<>setpagedevice" +*CloseUI: *PageSize + +*OpenUI *PageRegion: PickOne +*OrderDependency: 100 AnySetup *PageRegion +*DefaultPageRegion: Letter +*PageRegion Letter/US Letter: "<>setpagedevice" +*PageRegion A4/A4: "<>setpagedevice" +*PageRegion 11x17/11x17: "<>setpagedevice" +*PageRegion A3/A3: "<>setpagedevice" +*PageRegion A5/A5: "<>setpagedevice" +*PageRegion B5/B5 (JIS): "<>setpagedevice" +*PageRegion Env10/Envelope #10: "<>setpagedevice" +*PageRegion EnvC5/Envelope C5: "<>setpagedevice" +*PageRegion EnvDL/Envelope DL: "<>setpagedevice" +*PageRegion EnvISOB5/Envelope B5: "<>setpagedevice" +*PageRegion EnvMonarch/Envelope Monarch: "<>setpagedevice" +*PageRegion Executive/Executive: "<>setpagedevice" +*PageRegion Legal/US Legal: "<>setpagedevice" +*CloseUI: *PageRegion + +*DefaultImageableArea: Letter +*ImageableArea Letter/US Letter: "18 36 594 756" +*ImageableArea A4/A4: "18 36 577 806" +*ImageableArea 11x17/11x17: "18 36 774 1188" +*ImageableArea A3/A3: "18 36 824 1155" +*ImageableArea A5/A5: "18 36 403 559" +*ImageableArea B5/B5 (JIS): "18 36 498 693" +*ImageableArea Env10/Envelope #10: "18 36 279 648" +*ImageableArea EnvC5/Envelope C5: "18 36 441 613" +*ImageableArea EnvDL/Envelope DL: "18 36 294 588" +*ImageableArea EnvISOB5/Envelope B5: "18 36 481 673" +*ImageableArea EnvMonarch/Envelope Monarch: "18 36 261 504" +*ImageableArea Executive/Executive: "18 36 504 720" +*ImageableArea Legal/US Legal: "18 36 594 972" + +*DefaultPaperDimension: Letter +*PaperDimension Letter/US Letter: "612 792" +*PaperDimension A4/A4: "595 842" +*PaperDimension 11x17/11x17: "792 1224" +*PaperDimension A3/A3: "842 1191" +*PaperDimension A5/A5: "421 595" +*PaperDimension B5/B5 (JIS): "516 729" +*PaperDimension Env10/Envelope #10: "297 684" +*PaperDimension EnvC5/Envelope C5: "459 649" +*PaperDimension EnvDL/Envelope DL: "312 624" +*PaperDimension EnvISOB5/Envelope B5: "499 709" +*PaperDimension EnvMonarch/Envelope Monarch: "279 540" +*PaperDimension Executive/Executive: "522 756" +*PaperDimension Legal/US Legal: "612 1008" + +*OpenUI *Duplex/Double-Sided Printing: PickOne +*OrderDependency: 130 AnySetup *Duplex +*DefaultDuplex: None +*Duplex DuplexNoTumble/Long Edge (Standard): "<>setpagedevice" +*Duplex DuplexTumble/Short Edge (Flip): "<>setpagedevice" +*Duplex None/Off: "<>setpagedevice" +*CloseUI: *Duplex + +*OpenUI *Resolution/Resolution: PickOne +*OrderDependency: 90 AnySetup *Resolution +*DefaultResolution: 600x600dpi +*Resolution 150x150dpi/150x150 DPI: "<>setpagedevice" +*Resolution 300x300dpi/300x300 DPI: "<>setpagedevice" +*Resolution 600x600dpi/600x600 DPI: "<>setpagedevice" +*Resolution 1200x1200dpi/1200x1200 DPI: "<>setpagedevice" +*CloseUI: *Resolution + +*CloseGroup: General + + +*% Generic boilerplate PPD stuff as standard PostScript fonts and so on + +*DefaultFont: Courier +*Font AvantGarde-Book: Standard "(001.006S)" Standard ROM +*Font AvantGarde-BookOblique: Standard "(001.006S)" Standard ROM +*Font AvantGarde-Demi: Standard "(001.007S)" Standard ROM +*Font AvantGarde-DemiOblique: Standard "(001.007S)" Standard ROM +*Font Bookman-Demi: Standard "(001.004S)" Standard ROM +*Font Bookman-DemiItalic: Standard "(001.004S)" Standard ROM +*Font Bookman-Light: Standard "(001.004S)" Standard ROM +*Font Bookman-LightItalic: Standard "(001.004S)" Standard ROM +*Font Courier: Standard "(002.004S)" Standard ROM +*Font Courier-Bold: Standard "(002.004S)" Standard ROM +*Font Courier-BoldOblique: Standard "(002.004S)" Standard ROM +*Font Courier-Oblique: Standard "(002.004S)" Standard ROM +*Font Helvetica: Standard "(001.006S)" Standard ROM +*Font Helvetica-Bold: Standard "(001.007S)" Standard ROM +*Font Helvetica-BoldOblique: Standard "(001.007S)" Standard ROM +*Font Helvetica-Narrow: Standard "(001.006S)" Standard ROM +*Font Helvetica-Narrow-Bold: Standard "(001.007S)" Standard ROM +*Font Helvetica-Narrow-BoldOblique: Standard "(001.007S)" Standard ROM +*Font Helvetica-Narrow-Oblique: Standard "(001.006S)" Standard ROM +*Font Helvetica-Oblique: Standard "(001.006S)" Standard ROM +*Font NewCenturySchlbk-Bold: Standard "(001.009S)" Standard ROM +*Font NewCenturySchlbk-BoldItalic: Standard "(001.007S)" Standard ROM +*Font NewCenturySchlbk-Italic: Standard "(001.006S)" Standard ROM +*Font NewCenturySchlbk-Roman: Standard "(001.007S)" Standard ROM +*Font Palatino-Bold: Standard "(001.005S)" Standard ROM +*Font Palatino-BoldItalic: Standard "(001.005S)" Standard ROM +*Font Palatino-Italic: Standard "(001.005S)" Standard ROM +*Font Palatino-Roman: Standard "(001.005S)" Standard ROM +*Font Symbol: Special "(001.007S)" Special ROM +*Font Times-Bold: Standard "(001.007S)" Standard ROM +*Font Times-BoldItalic: Standard "(001.009S)" Standard ROM +*Font Times-Italic: Standard "(001.007S)" Standard ROM +*Font Times-Roman: Standard "(001.007S)" Standard ROM +*Font ZapfChancery-MediumItalic: Standard "(001.007S)" Standard ROM +*Font ZapfDingbats: Special "(001.004S)" Standard ROM + diff --git a/roles/cups_server/tasks/main.yml b/roles/cups_server/tasks/main.yml index 418a672..849543c 100644 --- a/roles/cups_server/tasks/main.yml +++ b/roles/cups_server/tasks/main.yml @@ -8,15 +8,17 @@ ansible.builtin.file: path: /etc/systemd/system/cups.service.d state: directory - mode: 0755 + mode: "0755" owner: root group: "{{ ansible_wheel }}" - name: Configure cups keytab location ansible.builtin.copy: dest: /etc/systemd/system/cups.service.d/keytab.conf - content: "[Service]\nEnvironment=KRB5_KTNAME=FILE:/etc/cups/cups.keytab\n" - mode: 0644 + content: | + [Service] + Environment=KRB5_KTNAME=FILE:/etc/cups/cups.keytab + mode: "0644" owner: root group: "{{ ansible_wheel }}" @@ -34,11 +36,18 @@ line: "#Listen 631" notify: Restart cups +- name: Share printers + ansible.builtin.lineinfile: + path: /etc/cups/cupsd.conf + line: "Port 631" + insertbefore: "^Listen .*.sock" + notify: Restart cups + - name: Set ssl listen port ansible.builtin.lineinfile: path: /etc/cups/cupsd.conf line: "SSLListen 631" - insertafter: "Listen /var/run/cups/cups.sock" + insertafter: "^Listen .*.sock" notify: Restart cups - name: Require tls 1.3 @@ -84,20 +93,28 @@ force: true notify: Restart cups -- name: Disable printer advertising +- name: Enable printer sharing ansible.builtin.lineinfile: path: /etc/cups/cupsd.conf regexp: "^Browsing .*" - line: "Browsing No" + line: "Browsing Yes" notify: Restart cups - name: Disable unauthenticated access from cups ansible.builtin.blockinfile: path: /etc/cups/cupsd.conf - insertafter: "^" - block: | - AuthType Default - Require user @foosh + marker: "{mark}" + marker_begin: "" + marker_end: "" + block: |2 + AuthType Default + Require group foosh + Order deny,allow + + + AuthType Default + Require group sysadm + Order deny,allow notify: Restart cups - name: Configure cups admin group @@ -111,7 +128,7 @@ ansible.builtin.copy: dest: "/usr/share/cups/www/{{ item }}" src: "{{ item }}" - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" with_items: @@ -122,7 +139,7 @@ ansible.builtin.copy: dest: /usr/share/cups/templates/header.tmpl src: header.tmpl - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" @@ -137,3 +154,91 @@ name: cups enabled: true state: started + +- name: Copy ppd files + ansible.builtin.copy: + dest: /usr/local/share/cups-ppd/ + src: cups-ppd/ + mode: "0644" + owner: root + group: "{{ ansible_wheel }}" + +- name: Get printers from LDAP + community.general.ldap_search: + attrs: + - cn + - description + - l + client_cert: >- + {{ hostvars[ansible_server]['tls_certs'] + '/' + ansible_server }}.crt + client_key: >- + {{ hostvars[ansible_server]['tls_private'] + '/' + ansible_server }}.key + dn: "{{ ldap_basedn }}" + filter: "(&(objectClass=device)(cn=*.print.foo.sh))" + scope: subordinate + server_uri: "ldaps://{{ ldap_server[0] }}" + delegate_to: localhost + register: printers + +- name: Get printers list + ansible.builtin.command: + argv: + - lpstat + - -e + changed_when: false + register: result + +- name: Add printers + ansible.builtin.command: + argv: + - lpadmin + - -D + - "{{ item.description }}" + - -i + - >- + {{ + '/usr/local/share/cups-ppd/' + + item.description | regex_replace(' ', '_') + + '.ppd' + }} + - -L + - "{{ item.l }}" + - -o + - media=a4 + - -o + - cupsSNMPSupplies=true + - -o + - printer-error-policy=abort-job + - -o + - printer-is-shared=true + - -v + - "http://{{ item.cn }}:631" + - -p + - "{{ item.cn | split('.') | first }}" + - -E + with_items: >- + {{ + printers.results | rejectattr( + 'cn', + 'in', + result.stdout_lines | map('regex_replace', '$', '.print.foo.sh' + ) | list) | list + }} + +- name: Remove printers + ansible.builtin.command: + argv: + - lpadmin + - -x + - "{{ item }}" + with_items: >- + {{ + result.stdout_lines | reject( + 'in', + printers.results | map(attribute='cn') | map( + 'regex_replace', + '.print.foo.sh$', + '' + ) | list + ) | list + }} diff --git a/roles/dhcpd/tasks/main.yml b/roles/dhcpd/tasks/main.yml index 8052208..134b4ed 100644 --- a/roles/dhcpd/tasks/main.yml +++ b/roles/dhcpd/tasks/main.yml @@ -7,16 +7,44 @@ name: "{{ dhcpd_package }}" state: installed +- name: Get host data from LDAP + community.general.ldap_search: + attrs: + - cn + - ipHostNumber + - macAddress + client_cert: >- + {{ hostvars[ansible_server]['tls_certs'] + '/' + ansible_server }}.crt + client_key: >- + {{ hostvars[ansible_server]['tls_private'] + '/' + ansible_server }}.key + dn: "{{ dhcpd_ldap_basedn | default(ldap_basedn) }}" + filter: "{{ dhcpd_ldap_filter }}" + scope: subordinate + server_uri: "ldaps://{{ ldap_server[0] }}" + delegate_to: localhost + register: ldap_hosts + when: dhcpd_ldap_filter is defined + - name: Create config ansible.builtin.template: dest: "{{ dhcpd_config }}" src: "{{ dhcpd_template | default('dhcpd.conf.j2') }}" - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" # validate: "dhcpd -t -cf %s" notify: Restart dhcpd +- name: Create leases file + ansible.builtin.copy: + dest: /var/db/isc-dhcp/dhcpd.leases + content: "" + mode: "0644" + owner: _isc-dhcp + group: _isc-dhcp + force: false + when: ansible_os_family == "OpenBSD" + - name: Enable service ansible.builtin.service: name: "{{ dhcpd_service }}" diff --git a/roles/dhcpd/templates/dhcpd.conf.cam.j2 b/roles/dhcpd/templates/dhcpd.conf.cam.j2 index edddc1a..54eff12 100644 --- a/roles/dhcpd/templates/dhcpd.conf.cam.j2 +++ b/roles/dhcpd/templates/dhcpd.conf.cam.j2 @@ -29,10 +29,12 @@ shared-network CAMNET { use-host-decl-names on; } - host ipcam01.cam.foo.sh { - option host-name "ipcam01.cam.foo.sh"; - hardware ethernet ec:71:db:6e:bc:0f; - fixed-address 172.20.26.101; +{% for host in ldap_hosts.results %} + host {{ host['cn'] }} { + option host-name "{{ host['cn'] }}"; + hardware ethernet {{ host['macAddress'] }}; + fixed-address {{ host['ipHostNumber'] }}; } +{% endfor %} } diff --git a/roles/dhcpd/templates/dhcpd.conf.j2 b/roles/dhcpd/templates/dhcpd.conf.j2 index 063a27f..7b41b05 100644 --- a/roles/dhcpd/templates/dhcpd.conf.j2 +++ b/roles/dhcpd/templates/dhcpd.conf.j2 @@ -52,7 +52,7 @@ shared-network FOOSH { option routers 172.20.20.1; option domain-name "home.foo.sh"; - option domain-name-servers 172.20.20.10, 172.20.21.1, 172.20.21.2; + option domain-name-servers 172.20.20.10, 172.20.20.11, 172.20.20.12; use-host-decl-names on; } diff --git a/roles/dhcpd/templates/dhcpd.conf.oob.j2 b/roles/dhcpd/templates/dhcpd.conf.oob.j2 new file mode 100644 index 0000000..b1a9034 --- /dev/null +++ b/roles/dhcpd/templates/dhcpd.conf.oob.j2 @@ -0,0 +1,40 @@ + +authorative; +ddns-update-style none; + +# logging +on commit { + log(info, + concat("Client ", + binary-to-ascii(16, 8, ":", substring(hardware, 1, 6)), + " requests ", + binary-to-ascii(16, 8, ":", option dhcp-parameter-request-list), + " - ", + pick-first-value(option vendor-class-identifier, "no vendor-id"), + " - ", + pick-first-value(option user-class, "no user-class")) + ); +} + +shared-network OOBNET { + + subnet 172.20.25.0 netmask 255.255.255.0 { + default-lease-time 86400; + max-lease-time 604800; + option subnet-mask 255.255.255.0; + option broadcast-address 172.20.25.255; + + option domain-name "oob.foo.sh"; + option domain-name-servers 172.20.25.1, 172.20.25.2, 172.20.25.3; + use-host-decl-names on; + } + +{% for host in ldap_hosts.results %} + host {{ host['cn'] }} { + option host-name "{{ host['cn'] }}"; + hardware ethernet {{ host['macAddress'] }}; + fixed-address {{ host['ipHostNumber'] }}; + } +{% endfor %} + +} diff --git a/roles/dhcpd/templates/dhcpd.conf.print.j2 b/roles/dhcpd/templates/dhcpd.conf.print.j2 index ca0ab35..da5c2e7 100644 --- a/roles/dhcpd/templates/dhcpd.conf.print.j2 +++ b/roles/dhcpd/templates/dhcpd.conf.print.j2 @@ -29,10 +29,12 @@ shared-network PRINTNET { use-host-decl-names on; } - host hp1.print.foo.sh { - option host-name "hp1.print.foo.sh"; - hardware ethernet 00:15:99:22:79:46; - fixed-address 172.20.24.101; +{% for host in ldap_hosts.results %} + host {{ host['cn'] }} { + option host-name "{{ host['cn'] }}"; + hardware ethernet {{ host['macAddress'] }}; + fixed-address {{ host['ipHostNumber'] }}; } +{% endfor %} } diff --git a/roles/dhparams/tasks/main.yml b/roles/dhparams/tasks/main.yml index e871137..74ce0bf 100644 --- a/roles/dhparams/tasks/main.yml +++ b/roles/dhparams/tasks/main.yml @@ -4,6 +4,6 @@ ansible.builtin.copy: dest: "{{ tls_certs }}/ffdhe3072.pem" src: ffdhe3072.pem - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" diff --git a/roles/docker/tasks/main.yml b/roles/docker/tasks/main.yml index d1f4b05..cc4b9b1 100644 --- a/roles/docker/tasks/main.yml +++ b/roles/docker/tasks/main.yml @@ -3,7 +3,7 @@ ansible.builtin.get_url: url: "https://download.docker.com/linux/{{ docker_osname }}/docker-ce.repo" dest: /etc/yum.repos.d/docker-ce.repo - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" @@ -12,17 +12,11 @@ name: docker-ce state: installed -- name: Enable user namespaces - ansible.posix.sysctl: - name: user.max_user_namespaces - value: "10240" - sysctl_file: /etc/sysctl.d/00-docker.conf - - name: Create config directory ansible.builtin.file: path: /etc/docker state: directory - mode: 0755 + mode: "0755" owner: root group: "{{ ansible_wheel }}" @@ -30,7 +24,7 @@ ansible.builtin.copy: dest: /etc/docker/daemon.json src: daemon.json - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" notify: Restart docker diff --git a/roles/docker_distribution/tasks/main.yml b/roles/docker_distribution/tasks/main.yml index 07c6c8b..cf85697 100644 --- a/roles/docker_distribution/tasks/main.yml +++ b/roles/docker_distribution/tasks/main.yml @@ -7,7 +7,7 @@ - name: Create docker group ansible.builtin.group: name: docker - gid: 1004 + gid: 311 - name: Create docker user ansible.builtin.user: @@ -18,13 +18,13 @@ groups: hostkey home: /var/empty shell: /sbin/nologin - uid: 1004 + uid: 311 - name: Create unit file drop-in directory ansible.builtin.file: path: /etc/systemd/system/docker-distribution.service.d state: directory - mode: 0755 + mode: "0755" owner: root group: "{{ ansible_wheel }}" @@ -32,7 +32,7 @@ ansible.builtin.copy: dest: /etc/systemd/system/docker-distribution.service.d/user.conf src: user.conf - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" notify: Restart docker-distribution @@ -41,7 +41,7 @@ ansible.builtin.template: dest: /etc/docker-distribution/registry/config.yml src: config.yml.j2 - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" notify: Restart docker-distribution @@ -50,7 +50,7 @@ ansible.builtin.file: path: /srv/registry/docker state: directory - mode: 0770 + mode: "0770" owner: root group: docker @@ -58,7 +58,7 @@ ansible.builtin.copy: dest: /etc/docker-distribution/registry/htpasswd src: "{{ htpasswd }}" - mode: 0640 + mode: "0640" owner: root group: docker when: htpasswd is defined diff --git a/roles/dovecot/tasks/main.yml b/roles/dovecot/tasks/main.yml index 01f9116..06932b1 100644 --- a/roles/dovecot/tasks/main.yml +++ b/roles/dovecot/tasks/main.yml @@ -8,16 +8,16 @@ ansible.builtin.include_role: name: keytab vars: - keytab: /etc/dovecot/dovecot.keytab - principals: + keytab_path: /etc/dovecot/dovecot.keytab + keytab_principals: - "imap/{{ mail_server }}@{{ kerberos_realm }}" - group: dovecot + keytab_group: dovecot - name: Install privatekey ansible.builtin.copy: dest: "{{ tls_private }}/{{ mail_server }}.key" src: "{{ item }}" - mode: 0600 + mode: "0600" owner: root group: "{{ ansible_wheel }}" with_first_found: @@ -30,7 +30,7 @@ ansible.builtin.copy: dest: "{{ tls_certs }}/{{ mail_server }}-fullchain.crt" src: "{{ item }}" - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" with_first_found: @@ -43,7 +43,7 @@ ansible.builtin.template: dest: /etc/dovecot/conf.d/99-local.conf src: local.conf.j2 - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" validate: doveconf -n %s @@ -58,7 +58,7 @@ ansible.builtin.file: path: "{{ item }}" state: directory - mode: 0755 + mode: "0755" owner: root group: "{{ ansible_wheel }}" setype: _default diff --git a/roles/dovecot/templates/local.conf.j2 b/roles/dovecot/templates/local.conf.j2 index 730072b..6276c88 100644 --- a/roles/dovecot/templates/local.conf.j2 +++ b/roles/dovecot/templates/local.conf.j2 @@ -1,14 +1,13 @@ -# https://ssl-config.mozilla.org/#server=dovecot&version=2.3.8&config=intermediate&openssl=1.1.1g&guideline=5.6 +# generated 2024-12-15, Mozilla Guideline v5.7, Dovecot 2.3.16, OpenSSL 3.2.2, modern config +# https://ssl-config.mozilla.org/#server=dovecot&version=2.3.16&config=modern&openssl=3.2.2&guideline=5.7 ssl = required ssl_cert = <{{ tls_certs }}/{{ mail_server }}-fullchain.crt ssl_key = <{{ tls_private }}/{{ mail_server }}.key -ssl_dh = <{{ tls_certs }}/ffdhe3072.pem - -ssl_min_protocol = TLSv1.2 -ssl_cipher_list = ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384 +ssl_min_protocol = TLSv1.3 ssl_prefer_server_ciphers = no +ssl_curve_list = X25519:prime256v1:secp384r1 # kerberos auth_gssapi_hostname = "$ALL" diff --git a/roles/forgejo/defaults/main.yml b/roles/forgejo/defaults/main.yml new file mode 100644 index 0000000..848f7a1 --- /dev/null +++ b/roles/forgejo/defaults/main.yml @@ -0,0 +1,7 @@ +--- +forgejo_url: >- + {{ + "https://codeberg.org/forgejo/forgejo/releases/download/v" + + forgejo_version + "/forgejo-" + forgejo_version + "-" + + ansible_system | lower + "-amd64" + }} diff --git a/roles/forgejo/files/forgejo.service b/roles/forgejo/files/forgejo.service new file mode 100644 index 0000000..289ccdc --- /dev/null +++ b/roles/forgejo/files/forgejo.service @@ -0,0 +1,16 @@ +[Unit] +Description=Forgejo (Beyond coding. We forge.) +After=syslog.target +After=network.target + +[Service] +Type=simple +User=forgejo +Group=forgejo +WorkingDirectory=/srv/forgejo +ExecStart=/usr/local/bin/forgejo web --config /etc/forgejo/app.ini +Restart=always +Environment=HOME=/srv/forgejo FORGEJO_WORK_DIR=/srv/forgejo + +[Install] +WantedBy=multi-user.target diff --git a/roles/zoneminder/handlers/main.yml b/roles/forgejo/handlers/main.yml similarity index 52% rename from roles/zoneminder/handlers/main.yml rename to roles/forgejo/handlers/main.yml index d34c003..4b650b4 100644 --- a/roles/zoneminder/handlers/main.yml +++ b/roles/forgejo/handlers/main.yml @@ -1,5 +1,5 @@ --- -- name: Restart zoneminder +- name: Restart forgejo ansible.builtin.service: - name: zoneminder + name: forgejo state: restarted diff --git a/roles/gitea_runner/meta/main.yml b/roles/forgejo/meta/main.yml similarity index 64% rename from roles/gitea_runner/meta/main.yml rename to roles/forgejo/meta/main.yml index 4dfd1ac..d5e8ce4 100644 --- a/roles/gitea_runner/meta/main.yml +++ b/roles/forgejo/meta/main.yml @@ -1,4 +1,4 @@ --- dependencies: - - {role: docker} - {role: git} + - {role: nginx} diff --git a/roles/gitea/tasks/main.yml b/roles/forgejo/tasks/main.yml similarity index 51% rename from roles/gitea/tasks/main.yml rename to roles/forgejo/tasks/main.yml index 208eed0..4b8c6f2 100644 --- a/roles/gitea/tasks/main.yml +++ b/roles/forgejo/tasks/main.yml @@ -1,79 +1,84 @@ --- +- name: Install dependencies + ansible.builtin.package: + name: git-lfs + state: installed + - name: Download binary ansible.builtin.get_url: - url: "{{ gitea_url }}" - checksum: "sha256:{{ gitea_url }}.sha256" - dest: /usr/local/bin/gitea - mode: 0755 + url: "{{ forgejo_url }}" + checksum: "sha256:{{ forgejo_url }}.sha256" + dest: /usr/local/bin/forgejo + mode: "0755" owner: root group: "{{ ansible_wheel }}" - notify: Restart gitea + notify: Restart forgejo - name: Create group ansible.builtin.group: - name: gitea + name: forgejo gid: 303 - name: Create user ansible.builtin.user: - name: gitea - comment: Service Gitea + name: forgejo + comment: Service Forgejo createhome: false - group: gitea + group: forgejo home: /var/empty shell: /sbin/nologin uid: 303 - name: Create config directory ansible.builtin.file: - path: /etc/gitea + path: /etc/forgejo state: directory - mode: 0750 + mode: "0750" owner: root - group: gitea + group: forgejo - name: Create config ansible.builtin.template: - dest: /etc/gitea/app.ini + dest: /etc/forgejo/app.ini src: app.ini.j2 - mode: 0640 + mode: "0640" owner: root - group: gitea - notify: Restart gitea + group: forgejo + notify: Restart forgejo - name: Create data directory ansible.builtin.file: - path: /export/gitea + path: /export/forgejo state: directory - mode: 0750 - owner: gitea - group: gitea + mode: "0750" + owner: forgejo + group: forgejo - name: Link data directory ansible.builtin.file: - path: /srv/gitea + path: /srv/forgejo state: link - src: /export/gitea + src: /export/forgejo owner: root group: "{{ ansible_wheel }}" follow: false - name: Create service file ansible.builtin.copy: - dest: /etc/systemd/system/gitea.service - src: gitea.service - mode: 0644 + dest: /etc/systemd/system/forgejo.service + src: forgejo.service + mode: "0644" owner: root group: "{{ ansible_wheel }}" - notify: Restart gitea + notify: Restart forgejo - name: Enable service ansible.builtin.service: - name: gitea + name: forgejo state: started enabled: true -- name: Allow nginx to connect gitea +- name: Allow nginx to connect forgejo ansible.posix.seboolean: name: httpd_can_network_connect state: true @@ -81,19 +86,22 @@ - name: Copy nginx config ansible.builtin.copy: - dest: "/etc/nginx/conf.d/{{ inventory_hostname }}/gitea.conf" + dest: "/etc/nginx/conf.d/{{ inventory_hostname }}/forgejo.conf" content: | + client_max_body_size 100m; location / { proxy_pass http://127.0.0.1:3000; } - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" notify: Restart nginx -- name: Add gitea alias for root +- name: Add forgejo alias for root ansible.builtin.blockinfile: - path: /root/.bash_profile + path: /root/.bashrc block: | - # run gitea as gitea user - alias gitea='sudo -u gitea HOME=/srv/gitea GITEA_WORK_DIR=/srv/gitea /usr/local/bin/gitea -c /etc/gitea/app.ini' + # run forgejo as forgejo user + alias forgejo='sudo -u forgejo HOME=/srv/forgejo \ + GITEA_WORK_DIR=/srv/forgejo \ + /usr/local/bin/forgejo -c /etc/forgejo/app.ini' diff --git a/roles/gitea/templates/app.ini.j2 b/roles/forgejo/templates/app.ini.j2 similarity index 76% rename from roles/gitea/templates/app.ini.j2 rename to roles/forgejo/templates/app.ini.j2 index 9ce2612..a8a7716 100644 --- a/roles/gitea/templates/app.ini.j2 +++ b/roles/forgejo/templates/app.ini.j2 @@ -1,21 +1,21 @@ APP_NAME = foo.sh - GIT -RUN_USER = gitea +RUN_USER = forgejo RUN_MODE = prod [database] DB_TYPE = mysql HOST = sqldb02.home.foo.sh -NAME = gitea -USER = gitea -PASSWD = {{ gitea_mysql_pass }} +NAME = forgejo +USER = forgejo +PASSWD = {{ forgejo_mysql_pass }} SCHEMA = SSL_MODE = true CHARSET = utf8 -PATH = /srv/gitea/data/gitea.db +PATH = /srv/forgejo/data/forgejo.db LOG_SQL = false [repository] -ROOT = /srv/gitea/data/gitea-repositories +ROOT = /srv/forgejo/data/forgejo-repositories [server] SSH_DOMAIN = localhost @@ -26,11 +26,11 @@ ROOT_URL = https://git.foo.sh/ DISABLE_SSH = true SSH_PORT = 22 LFS_START_SERVER = true -LFS_JWT_SECRET = {{ gitea_lfs_jwt_secret }} +LFS_JWT_SECRET = {{ forgejo_lfs_jwt_secret }} OFFLINE_MODE = false [lfs] -PATH = /srv/gitea/data/lfs +PATH = /srv/forgejo/data/lfs [mailer] ENABLED = false @@ -57,8 +57,6 @@ PROVIDER = file [log] MODE = console LEVEL = info -ROOT_PATH = /srv/gitea/log -ROUTER = console [repository.pull-request] DEFAULT_MERGE_STYLE = merge @@ -68,10 +66,13 @@ DEFAULT_TRUST_MODEL = committer [security] INSTALL_LOCK = true -INTERNAL_TOKEN = {{ gitea_internal_token }} +INTERNAL_TOKEN = {{ forgejo_internal_token }} PASSWORD_HASH_ALGO = pbkdf2 REVERSE_PROXY_TRUSTED_PROXIES = 127.0.0.0/8,::1/128 REVERSE_PROXY_LIMIT = 1 [actions] ENABLED = true + +[oauth2] +JWT_SECRET = {{ forgejo_oauth_jwt_secret }} diff --git a/roles/frigate/defaults/main.yml b/roles/frigate/defaults/main.yml new file mode 100644 index 0000000..3266cf2 --- /dev/null +++ b/roles/frigate/defaults/main.yml @@ -0,0 +1,2 @@ +--- +frigate_version: stable diff --git a/roles/frigate/files/99-frigate.rules b/roles/frigate/files/99-frigate.rules new file mode 100644 index 0000000..9d5516e --- /dev/null +++ b/roles/frigate/files/99-frigate.rules @@ -0,0 +1,2 @@ +SUBSYSTEM=="usb", ATTRS{idVendor}=="18d1", ATTRS{idProduct}=="9302", MODE="0660", GROUP="frigate" +SUBSYSTEM=="usb", ATTRS{idVendor}=="1a6e", ATTRS{idProduct}=="089a", MODE="0660", GROUP="frigate" diff --git a/roles/frigate/handlers/main.yml b/roles/frigate/handlers/main.yml new file mode 100644 index 0000000..9b0555a --- /dev/null +++ b/roles/frigate/handlers/main.yml @@ -0,0 +1,12 @@ +--- +- name: Clear preview restart cache + ansible.builtin.file: + path: /srv/frigate/media/clips/preview_restart_cache + state: absent + listen: Restart frigate + +- name: Restart frigate + ansible.builtin.systemd_service: + name: frigate-container + state: restarted + daemon_reload: true diff --git a/roles/frigate/meta/main.yml b/roles/frigate/meta/main.yml new file mode 100644 index 0000000..9699a03 --- /dev/null +++ b/roles/frigate/meta/main.yml @@ -0,0 +1,5 @@ +--- +dependencies: + - {role: apache} + - {role: podman} + - {role: udev} diff --git a/roles/frigate/tasks/main.yml b/roles/frigate/tasks/main.yml new file mode 100644 index 0000000..7401e1f --- /dev/null +++ b/roles/frigate/tasks/main.yml @@ -0,0 +1,153 @@ +--- +- name: Create group + ansible.builtin.group: + name: frigate + +- name: Create user + ansible.builtin.user: + name: frigate + comment: Podman Frigate + group: frigate + shell: /sbin/nologin + +- name: Enable user lingering + ansible.builtin.command: + argv: + - loginctl + - enable-linger + - frigate + creates: /var/lib/systemd/linger/frigate + +- name: Allow podman to use devices + ansible.posix.seboolean: + name: container_use_devices + state: true + persistent: true + +- name: Allow frigate to connect specific devices + ansible.builtin.copy: + dest: /etc/udev/rules.d/99-frigate.rules + src: 99-frigate.rules + mode: "0644" + owner: root + group: "{{ ansible_wheel }}" + notify: Reload udev rules + +- name: Copy host key + ansible.builtin.copy: + dest: "{{ tls_private }}/frigate.key" + src: "{{ tls_private }}/{{ inventory_hostname }}.key" + mode: "0640" + owner: root + group: frigate + remote_src: true + notify: Restart frigate + +- name: Get cameras from LDAP + community.general.ldap_search: + attrs: + - cn + - l + client_cert: >- + {{ hostvars[ansible_server]['tls_certs'] + '/' + ansible_server }}.crt + client_key: >- + {{ hostvars[ansible_server]['tls_private'] + '/' + ansible_server }}.key + dn: "{{ ldap_basedn }}" + filter: (&(objectClass=ipHost)(cn=ipcam*.cam.foo.sh)) + scope: subordinate + server_uri: "ldaps://{{ ldap_server[0] }}" + delegate_to: localhost + register: ldap_cams + +- name: Create config + ansible.builtin.template: + dest: /etc/frigate.yml + src: frigate.yml.j2 + mode: "0640" + owner: root + group: frigate + notify: Restart frigate + +- name: Fix SELinux contexts from data directory + community.general.sefcontext: + path: /export/frigate(/.*)? + setype: container_file_t + when: ansible_selinux_python_present + +- name: Create base directory + ansible.builtin.file: + path: /export/frigate + state: directory + mode: "0755" + owner: root + group: root + setype: _default + +- name: Create data directories + ansible.builtin.file: + path: "{{ item }}" + state: directory + mode: "0770" + owner: root + group: frigate + setype: _default + with_items: + - /export/frigate/config + - /export/frigate/media + +- name: Link data directory + ansible.builtin.file: + dest: /srv/frigate + src: /export/frigate + state: link + owner: root + group: "{{ ansible_wheel }}" + follow: false + +- name: Create service file + ansible.builtin.template: + dest: /etc/systemd/system/frigate-container.service + src: frigate-container.service.j2 + mode: "0644" + owner: root + group: "{{ ansible_wheel }}" + notify: Restart frigate + +- name: Create environment config for service + ansible.builtin.template: + dest: /etc/sysconfig/frigate-container + src: frigate-container.sysconfig.j2 + mode: "0600" + owner: root + group: "{{ ansible_wheel }}" + notify: Restart frigate + +- name: Enable service + ansible.builtin.service: + name: frigate-container + state: started + enabled: true + +- name: Copy apache config + ansible.builtin.copy: + dest: /etc/httpd/conf.local.d/frigate-container.conf + content: | + ProxyPass /frigate/ http://127.0.0.1:8007/ + ProxyPassReverse /frigate/ http://127.0.0.1:8007/ + + ProxyPass /frigate/ws ws://127.0.0.1:8007/ws + ProxyPassReverse /frigate/ws ws://127.0.0.1:8007/ws + + ProxyPass /frigate/live ws://127.0.0.1:8007/live + ProxyPassReverse /frigate/live ws://127.0.0.1:8007/live + + + RewriteEngine on + RewriteCond %{HTTP:Upgrade} =websocket [NC] + RewriteRule /(.*) ws://127.0.0.1:8007/$1 [P,L] + RewriteCond %{HTTP:Upgrade} !=websocket [NC] + RewriteRule /(.*) http://127.0.0.1:8007/$1 [P,L] + mode: "0644" + owner: root + group: "{{ ansible_wheel }}" + notify: Restart apache diff --git a/roles/frigate/templates/frigate-container.service.j2 b/roles/frigate/templates/frigate-container.service.j2 new file mode 100644 index 0000000..8766bb6 --- /dev/null +++ b/roles/frigate/templates/frigate-container.service.j2 @@ -0,0 +1,25 @@ +[Unit] +Description=Frigate Container +Wants=network-online.target +After=network-online.target + +[Service] +User=frigate +EnvironmentFile=/etc/sysconfig/frigate-container +ExecStart=/usr/bin/podman run \ + --rm -p 127.0.0.1:8007:5000 \ + --name frigate \ + --volume {{ tls_certs }}/ca.crt:/etc/ssl/certs/ca.crt:ro \ + --volume {{ tls_certs }}/{{ inventory_hostname }}.crt:/etc/ssl/certs/{{ inventory_hostname }}.crt:ro \ + --volume {{ tls_private }}/frigate.key:/etc/ssl/private/{{ inventory_hostname }}.key:ro \ + --volume /srv/frigate/config:/config:rw \ + --volume /etc/frigate.yml:/config/config.yml:ro \ + --volume /srv/frigate/media:/media/frigate:rw \ + --volume /dev/bus/usb:/dev/bus/usb:rw \ + --shm-size 1024M \ + --env=FRIGATE_* ghcr.io/blakeblackshear/frigate:{{ frigate_version }} +ExecStop=/usr/bin/podman stop --ignore frigate +ExecStopPost=/usr/bin/podman rm -f --ignore frigate + +[Install] +WantedBy=multi-user.target diff --git a/roles/frigate/templates/frigate-container.sysconfig.j2 b/roles/frigate/templates/frigate-container.sysconfig.j2 new file mode 100644 index 0000000..1f9f038 --- /dev/null +++ b/roles/frigate/templates/frigate-container.sysconfig.j2 @@ -0,0 +1,3 @@ +{% for camera in ldap_cams.results %} +FRIGATE_{{ camera['l'] | upper }}_PASS="{{ cctv_cameras[camera['cn']] }}" +{% endfor %} diff --git a/roles/frigate/templates/frigate.yml.j2 b/roles/frigate/templates/frigate.yml.j2 new file mode 100644 index 0000000..c269f6d --- /dev/null +++ b/roles/frigate/templates/frigate.yml.j2 @@ -0,0 +1,41 @@ +--- +mqtt: + enabled: true + host: mqtt02.home.foo.sh + port: 8883 + topic_prefix: frigate/{{ inventory_hostname }} + client_id: {{ inventory_hostname }} + tls_ca_certs: /etc/ssl/certs/ca.crt + tls_client_cert: /etc/ssl/certs/{{ inventory_hostname }}.crt + tls_client_key: /etc/ssl/private/{{ inventory_hostname }}.key + +detectors: + coral: + type: edgetpu + device: usb + +record: + enabled: true + retain: + days: 7 + mode: motion + detections: + retain: + days: 30 + mode: motion + +cameras: +{% for camera in ldap_cams.results %} + {{ camera['l'] }}: + enabled: true + ffmpeg: + inputs: + - path: "rtsp://viewer:{FRIGATE_{{ camera['l'] | upper }}_PASS}@{{ camera['cn'] }}/h264Preview_01_sub" + input_args: preset-rtsp-restream + roles: + - detect + - path: "rtsp://viewer:{FRIGATE_{{ camera['l'] | upper }}_PASS}@{{ camera['cn'] }}/h264Preview_01_main" + input_args: preset-rtsp-restream + roles: + - record +{% endfor %} diff --git a/roles/fwupd/tasks/main.yml b/roles/fwupd/tasks/main.yml new file mode 100644 index 0000000..5e71293 --- /dev/null +++ b/roles/fwupd/tasks/main.yml @@ -0,0 +1,11 @@ +--- +- name: Install packages + ansible.builtin.package: + name: fwupd + state: installed + +- name: Enable LVFS + ansible.builtin.lineinfile: + path: /etc/fwupd/remotes.d/lvfs.conf + regexp: "^Enabled=.*" + line: "Enabled=true" diff --git a/roles/git_server/tasks/main.yml b/roles/git_server/tasks/main.yml index 889897c..2e22a61 100644 --- a/roles/git_server/tasks/main.yml +++ b/roles/git_server/tasks/main.yml @@ -17,7 +17,7 @@ ansible.builtin.file: path: /export/git state: directory - mode: 0755 + mode: "0755" owner: root group: "{{ ansible_wheel }}" @@ -33,7 +33,7 @@ ansible.builtin.copy: dest: /etc/gitweb.conf src: gitweb.conf - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" @@ -41,7 +41,7 @@ ansible.builtin.copy: dest: /var/www/git/robots.txt content: "User-agent: *\nDisallow:\n" - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" @@ -49,7 +49,7 @@ ansible.builtin.copy: dest: "/var/www/git/static/{{ item }}" src: "{{ item }}" - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" with_items: @@ -60,7 +60,7 @@ ansible.builtin.copy: dest: /etc/httpd/conf.local.d/git.conf src: git.conf - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" notify: Restart apache diff --git a/roles/gitea/defaults/main.yml b/roles/gitea/defaults/main.yml deleted file mode 100644 index 6a37123..0000000 --- a/roles/gitea/defaults/main.yml +++ /dev/null @@ -1,2 +0,0 @@ ---- -gitea_url: "https://dl.gitea.com/gitea/{{ gitea_version }}/gitea-{{ gitea_version }}-{{ ansible_system | lower }}-amd64" diff --git a/roles/gitea/files/gitea.service b/roles/gitea/files/gitea.service deleted file mode 100644 index 0dfec4a..0000000 --- a/roles/gitea/files/gitea.service +++ /dev/null @@ -1,16 +0,0 @@ -[Unit] -Description=Gitea (Git with a cup of tea) -After=syslog.target -After=network.target - -[Service] -Type=simple -User=gitea -Group=gitea -WorkingDirectory=/srv/gitea -ExecStart=/usr/local/bin/gitea web --config /etc/gitea/app.ini -Restart=always -Environment=HOME=/srv/gitea GITEA_WORK_DIR=/srv/gitea - -[Install] -WantedBy=multi-user.target diff --git a/roles/gitea/meta/main.yml b/roles/gitea/meta/main.yml deleted file mode 100644 index f9c5d0d..0000000 --- a/roles/gitea/meta/main.yml +++ /dev/null @@ -1,4 +0,0 @@ ---- -dependencies: - - {role: git} - - {role: nginx/server} diff --git a/roles/gitea_runner/defaults/main.yml b/roles/gitea_runner/defaults/main.yml deleted file mode 100644 index bb9e11e..0000000 --- a/roles/gitea_runner/defaults/main.yml +++ /dev/null @@ -1,2 +0,0 @@ ---- -gitea_runner_version: main diff --git a/roles/gitea_runner/files/act_runner.service b/roles/gitea_runner/files/act_runner.service deleted file mode 100644 index 1533c88..0000000 --- a/roles/gitea_runner/files/act_runner.service +++ /dev/null @@ -1,14 +0,0 @@ -[Unit] -Description=Act Runner for Gitea -After=syslog.target -After=network.target - -[Service] -User=act_runner -Group=act_runner -WorkingDirectory=/var/lib/act_runner -Environment=HOME=/var/lib/act_runner -ExecStart=/usr/local/bin/act_runner daemon -c /var/lib/act_runner/config.yml - -[Install] -WantedBy=multi-user.target diff --git a/roles/gitea_runner/files/config.yml b/roles/gitea_runner/files/config.yml deleted file mode 100644 index bd7abba..0000000 --- a/roles/gitea_runner/files/config.yml +++ /dev/null @@ -1,50 +0,0 @@ ---- -log: - # The level of logging, can be trace, debug, info, warn, error, fatal - level: info - -runner: - # Where to store the registration result. - file: .runner - # Execute how many tasks concurrently at the same time. - capacity: 1 - # Extra environment variables to run jobs from a file. - # It will be ignored if it's empty or the file doesn't exist. - env_file: .env - # The timeout for a job to be finished. - # Please note that the Gitea instance also has a timeout (3h by default) - # for the job. So the job could be stopped by the Gitea instance if it's - # timeout is shorter than this. - timeout: 3h - # Whether skip verifying the TLS certificate of the Gitea instance. - insecure: false - # The timeout for fetching the job from the Gitea instance. - fetch_timeout: 5s - # The interval for fetching the job from the Gitea instance. - fetch_interval: 2s - -cache: - # Enable cache server to use actions/cache. - enabled: true - # The directory to store the cache data. - # If it's empty, the cache data will be stored in $HOME/.cache/actcache. - dir: "" - # The host of the cache server. - # It's not for the address to listen, but the address to connect from job - # containers. So 0.0.0.0 is a bad choice, leave it empty to detect - # automatically. - host: "" - # The port of the cache server. - # 0 means to use a random available port. - port: 0 - -container: - # Which network to use for the job containers. Could be bridge, host, none, - # or the name of a custom network. - network_mode: bridge - # Whether to use privileged mode or not when launching task containers - # (privileged mode is required for Docker-in-Docker). - privileged: false - # And other options to be used when the container is started - # (eg, --add-host=my.gitea.url:host-gateway). - options: diff --git a/roles/gitea_runner/tasks/main.yml b/roles/gitea_runner/tasks/main.yml deleted file mode 100644 index 740a914..0000000 --- a/roles/gitea_runner/tasks/main.yml +++ /dev/null @@ -1,85 +0,0 @@ ---- -- name: Create group - ansible.builtin.group: - name: act_runner - system: true - -- name: Create user - ansible.builtin.user: - name: act_runner - system: true - comment: Gitea act_runner - create_home: false - home: /var/empty - group: act_runner - groups: - - docker - shell: /sbin/nologin - -- name: Install dependencies - ansible.builtin.package: - name: golang - state: installed - -- name: Download binary - ansible.builtin.get_url: - url: > - {{ - "https://gitea.com/gitea/act_runner/releases/download/v" + - gitea_runner_version + "/act_runner-" + gitea_runner_version + - "-" + ansible_system | lower + "-amd64" - }} - dest: /usr/local/bin/act_runner - mode: 0755 - owner: root - group: "{{ ansible_wheel }}" - notify: Restart act_runner - -- name: Create config directory - ansible.builtin.file: - path: /var/lib/act_runner - state: directory - mode: 0750 - owner: root - group: act_runner - -- name: Copy config file - ansible.builtin.copy: - dest: /var/lib/act_runner/.runner - src: "/srv/private/files/act_runner/{{ inventory_hostname }}.conf" - mode: 0640 - owner: root - group: act_runner - notify: Restart act_runner - -- name: Copy config file - ansible.builtin.copy: - dest: /var/lib/act_runner/config.yml - src: config.yml - mode: 0640 - owner: root - group: act_runner - notify: Restart act_runner - -- name: Create cache directory - ansible.builtin.file: - path: /var/lib/act_runner/.cache - state: directory - mode: 0770 - owner: root - group: act_runner - notify: Restart act_runner - -- name: Copy unit file - ansible.builtin.copy: - dest: /etc/systemd/system/act_runner.service - src: act_runner.service - mode: 0644 - owner: root - group: root - -- name: Enable service - ansible.builtin.service: - name: act_runner - state: started - enabled: true diff --git a/roles/google_spell_pspell/files/google-spell-pspell-container.service b/roles/google_spell_pspell/files/google-spell-pspell-container.service new file mode 100644 index 0000000..705ff29 --- /dev/null +++ b/roles/google_spell_pspell/files/google-spell-pspell-container.service @@ -0,0 +1,16 @@ +[Unit] +Description=google-spell-pspell Container +Wants=network-online.target +After=network-online.target + +[Service] +User=pspell +ExecStart=/usr/bin/podman run \ + --rm -p 127.0.0.1:8010:80 \ + --name google-spell-pspell \ + google-spell-pspell:latest +ExecStop=/usr/bin/podman stop --ignore google-spell-pspell +ExecStopPost=/usr/bin/podman rm -f --ignore google-spell-pspell + +[Install] +WantedBy=multi-user.target diff --git a/roles/google_spell_pspell/handlers/main.yml b/roles/google_spell_pspell/handlers/main.yml new file mode 100644 index 0000000..c6f29db --- /dev/null +++ b/roles/google_spell_pspell/handlers/main.yml @@ -0,0 +1,18 @@ +--- +- name: Rebuild google-spell-pspell-container + ansible.builtin.command: + argv: + - podman + - build + - -t + - google-spell-pspell + - /usr/local/src/docker-google-spell-pspell + become: true + become_user: pspell + notify: Restart google-spell-pspell-container + +- name: Restart google-spell-pspell-container + ansible.builtin.service: + name: google-spell-pspell-container + daemon_reload: true + state: restarted diff --git a/roles/google_spell_pspell/meta/main.yml b/roles/google_spell_pspell/meta/main.yml new file mode 100644 index 0000000..b8e2a3e --- /dev/null +++ b/roles/google_spell_pspell/meta/main.yml @@ -0,0 +1,5 @@ +--- +dependencies: + - {role: git} + - {role: nginx} + - {role: podman} diff --git a/roles/google_spell_pspell/tasks/main.yml b/roles/google_spell_pspell/tasks/main.yml new file mode 100644 index 0000000..2fe09ee --- /dev/null +++ b/roles/google_spell_pspell/tasks/main.yml @@ -0,0 +1,54 @@ +--- +- name: Create group + ansible.builtin.group: + name: pspell + +- name: Create user + ansible.builtin.user: + name: pspell + comment: Podman google-spell-pspell + group: pspell + shell: /sbin/nologin + +- name: Enable user lingering + ansible.builtin.command: + argv: + - loginctl + - enable-linger + - pspell + creates: /var/lib/systemd/linger/pspell + +- name: Get container source + ansible.builtin.git: + dest: /usr/local/src/docker-google-spell-pspell + repo: https://github.com/foo-sh/docker-google-spell-pspell.git + update: true + version: main + notify: Rebuild google-spell-pspell-container + +- name: Create service file + ansible.builtin.copy: + dest: /etc/systemd/system/google-spell-pspell-container.service + src: google-spell-pspell-container.service + mode: "0644" + owner: root + group: "{{ ansible_wheel }}" + notify: Restart google-spell-pspell-container + +- name: Enable service + ansible.builtin.service: + name: google-spell-pspell-container + state: started + enabled: true + +- name: Copy nginx config + ansible.builtin.copy: + dest: "/etc/nginx/conf.d/{{ inventory_hostname }}/google-spell-pspell.conf" + content: | + location /tbproxy/spell { + proxy_pass http://127.0.0.1:8010/; + } + mode: "0644" + owner: root + group: "{{ ansible_wheel }}" + notify: Restart nginx diff --git a/roles/grafana/tasks/main.yml b/roles/grafana/tasks/main.yml index 3ed3db6..4b59f21 100644 --- a/roles/grafana/tasks/main.yml +++ b/roles/grafana/tasks/main.yml @@ -10,11 +10,19 @@ group: grafana shell: /sbin/nologin +- name: Enable user lingering + ansible.builtin.command: + argv: + - loginctl + - enable-linger + - grafana + creates: /var/lib/systemd/linger/grafana + - name: Copy host key ansible.builtin.copy: dest: "{{ tls_private }}/grafana.key" src: "{{ tls_private }}/{{ inventory_hostname }}.key" - mode: 0640 + mode: "0640" owner: root group: grafana remote_src: true @@ -23,7 +31,7 @@ ansible.builtin.template: dest: /etc/sysconfig/grafana-container src: grafana-container.sysconfig.j2 - mode: 0600 + mode: "0600" owner: root group: "{{ ansible_wheel }}" notify: Restart grafana @@ -32,7 +40,7 @@ ansible.builtin.template: dest: /etc/systemd/system/grafana-container.service src: grafana-container.service.j2 - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" notify: Restart grafana @@ -41,7 +49,7 @@ ansible.builtin.template: dest: /etc/grafana-ldap.toml src: grafana-ldap.toml.j2 - mode: 0640 + mode: "0640" owner: root group: grafana notify: Restart grafana @@ -58,9 +66,9 @@ content: | location /grafana/ { proxy_set_header Host noc.foo.sh; - proxy_pass http://localhost:8002/; + proxy_pass http://127.0.0.1:8002/; } - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" notify: Restart nginx diff --git a/roles/grossd/meta/main.yml b/roles/grossd/meta/main.yml index 7ae8670..50b8afb 100644 --- a/roles/grossd/meta/main.yml +++ b/roles/grossd/meta/main.yml @@ -1,3 +1,4 @@ --- dependencies: + - {role: crb_repo} - {role: foosh_repo} diff --git a/roles/grossd/tasks/main.yml b/roles/grossd/tasks/main.yml index fe75f97..74079d3 100644 --- a/roles/grossd/tasks/main.yml +++ b/roles/grossd/tasks/main.yml @@ -8,7 +8,7 @@ ansible.builtin.file: path: /var/db/grossd state: directory - mode: 0750 + mode: "0750" owner: gross group: "{{ ansible_wheel }}" @@ -16,7 +16,7 @@ ansible.builtin.copy: dest: /etc/grossd.conf src: grossd.conf - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" notify: Restart grossd diff --git a/roles/ha_mqtt_configd/files/ha_mqtt_configd.py b/roles/ha_mqtt_configd/files/ha_mqtt_configd.py new file mode 100755 index 0000000..bc1c3e7 --- /dev/null +++ b/roles/ha_mqtt_configd/files/ha_mqtt_configd.py @@ -0,0 +1,71 @@ +#!/usr/bin/env python3 + +import hashlib +import json +import paho.mqtt.client as mqtt +import socket +import ssl +import syslog +import time + +notify = {} + + +def on_message(client, userdata, msg): + if not msg.topic in notify: + syslog.syslog(syslog.LOG_INFO, f"Publish config for {msg.topic}") + elif notify[msg.topic] < time.monotonic() - 600: + syslog.syslog(syslog.LOG_INFO, f"Refresh config for {msg.topic}") + else: + return + topic = msg.topic.split("/") + uniqueid = hashlib.md5(msg.topic.encode()).hexdigest() + config = { + "dev": { + "name": topic[2].capitalize(), + "suggested_area": topic[1].capitalize().replace("_", " "), + "identifiers": [ + uniqueid, + ], + }, + "icon": "mdi:lightning-bolt", + "name": "Power Usage", + "state_topic": msg.topic, + "unit_of_measurement": "W", + "unique_id": uniqueid, + } + client.publish( + topic=f"homeassistant/sensor/{uniqueid}/config", payload=json.dumps(config) + ) + notify[msg.topic] = time.monotonic() + + +def connect(hostname): + client = mqtt.Client(protocol=mqtt.MQTTv5) + client.tls_set( + certfile=f"/etc/ssl/{socket.gethostname()}.crt", + keyfile=f"/etc/ssl/private/{socket.gethostname()}.key", + ca_certs="/etc/ssl/ca.crt", + cert_reqs=ssl.CERT_REQUIRED, + ) + client.on_message = on_message + client.connect(hostname, 8883) + syslog.syslog(syslog.LOG_INFO, f"Connected to MQTT broker {hostname}") + return client + + +def main(): + syslog.openlog( + "ha_mqtt_configd", logoption=syslog.LOG_PID, facility=syslog.LOG_DAEMON + ) + client = connect(socket.gethostname()) + try: + client.subscribe("home/+/+/power") + client.loop_forever() + except KeyboardInterrupt: + client.disconnect() + syslog.closelog() + + +if __name__ == "__main__": + main() diff --git a/roles/ha_mqtt_configd/files/ha_mqtt_configd.rc b/roles/ha_mqtt_configd/files/ha_mqtt_configd.rc new file mode 100755 index 0000000..dc63988 --- /dev/null +++ b/roles/ha_mqtt_configd/files/ha_mqtt_configd.rc @@ -0,0 +1,12 @@ +#!/bin/ksh + +daemon="/usr/local/sbin/ha_mqtt_configd" +daemon_user="ha-mqtt" + +. /etc/rc.d/rc.subr + +rc_bg=YES +rc_reload=NO +pexp="python3 /usr/local/sbin/ha_mqtt_configd" + +rc_cmd $1 diff --git a/roles/ha_mqtt_configd/handlers/main.yml b/roles/ha_mqtt_configd/handlers/main.yml new file mode 100644 index 0000000..79a2cc5 --- /dev/null +++ b/roles/ha_mqtt_configd/handlers/main.yml @@ -0,0 +1,5 @@ +--- +- name: Restart ha_mqtt_configd + ansible.builtin.service: + name: ha_mqtt_configd + state: restarted diff --git a/roles/ha_mqtt_configd/tasks/main.yml b/roles/ha_mqtt_configd/tasks/main.yml new file mode 100644 index 0000000..0757fa8 --- /dev/null +++ b/roles/ha_mqtt_configd/tasks/main.yml @@ -0,0 +1,45 @@ +--- +- name: Install packages + ansible.builtin.package: + name: py3-paho-mqtt + state: installed + +- name: Create group + ansible.builtin.group: + name: ha-mqtt + system: true + +- name: Create user + ansible.builtin.user: + name: ha-mqtt + comment: ha-mqtt-configd + group: ha-mqtt + groups: hostkey + create_home: false + home: /var/empty + shell: /sbin/nologin + system: true + +- name: Copy daemon + ansible.builtin.copy: + dest: /usr/local/sbin/ha_mqtt_configd + src: ha_mqtt_configd.py + mode: "0755" + owner: root + group: "{{ ansible_wheel }}" + notify: Restart ha_mqtt_configd + +- name: Copy startup script + ansible.builtin.copy: + dest: /etc/rc.d/ha_mqtt_configd + src: ha_mqtt_configd.rc + mode: "0755" + owner: root + group: "{{ ansible_wheel }}" + notify: Restart ha_mqtt_configd + +- name: Enable service + ansible.builtin.service: + name: ha_mqtt_configd + state: started + enabled: true diff --git a/roles/homeassistant/files/99-homeassistant.rules b/roles/homeassistant/files/99-homeassistant.rules new file mode 100644 index 0000000..04728a9 --- /dev/null +++ b/roles/homeassistant/files/99-homeassistant.rules @@ -0,0 +1 @@ +SUBSYSTEM=="tty", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", MODE="0660", GROUP="homeassistant" diff --git a/roles/homeassistant/files/auth-command.py b/roles/homeassistant/files/auth-command.py new file mode 100755 index 0000000..02fff52 --- /dev/null +++ b/roles/homeassistant/files/auth-command.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 + +import os +import re +import sys +import requests + +username = os.environ.get("username") +password = os.environ.get("password") + +if username is None or password is None: + sys.exit(2) +if not re.search(r"^[a-z]+$", username): + sys.exit(2) + +resp = requests.post( + "https://id.foo.sh/authcheck", + json={"username": username, "password": password, "group": "foosh"}, +) +if resp.status_code != 200: + sys.exit(2) + +print("name = {}".format(resp.json()["name"])) +print("group = system-users") +print("local_only = false") diff --git a/roles/homeassistant/files/auth-command.sh b/roles/homeassistant/files/auth-command.sh deleted file mode 100755 index 6b2c2dc..0000000 --- a/roles/homeassistant/files/auth-command.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/sh - -set -eu - -if [ "$(echo "$username" | sed -r 's/^[a-z]+$/x/')" != "x" ]; then - exit 2 -fi - -curl -sf -X POST -H "Content-Type: application/json" -d @- \ - https://id.foo.sh/authcheck </dev/null 2>&1 || true +-delgroup "$GROUP" >/dev/null 2>&1 || true +- +-# Re-use existing group (can't delgroup a group that is in use) +-group="$(getent group "$PGID" | cut -d: -f1 || true)" +-if [ -z "$group" ]; then +- addgroup -g "$PGID" "$GROUP" +-else +- bashio::log.notice "Re-using existing group with gid $PGID: $group" +- GROUP="$group" +-fi +- +-# Replace existing user (ensures correct shell and primary group) +-user="$(getent passwd "$PUID" | cut -d: -f1 || true)" +-if [ -n "$user" ]; then +- bashio::log.notice "Replacing existing user with uid $PUID: $user" +- deluser "$user" +-fi +-adduser -G "$GROUP" -D -u "$PUID" "$USER" ++if [ "$(whoami)" != "homeassistant" ]; then + +-if [ -n "${EXTRA_GID:-}" ]; then +- bashio::log.info "Resolving supplementary GIDs: $EXTRA_GID" +- supplementary_groups=() +- +- for gid in $EXTRA_GID; do +- group="$(getent group "$gid" | cut -d: -f1 || true)" +- +- if [ -z "$group" ]; then +- group="$USER-$gid" +- addgroup -g "$gid" "$group" +- fi ++ # Some HA commands seem to fail if we don't have an actual user. ++ # ie: shell_command would return error code 255 ++ bashio::log.info "Creating user $USER with $PUID:$PGID" ++ ++ deluser "$USER" >/dev/null 2>&1 || true ++ delgroup "$GROUP" >/dev/null 2>&1 || true ++ ++ # Re-use existing group (can't delgroup a group that is in use) ++ group="$(getent group "$PGID" | cut -d: -f1 || true)" ++ if [ -z "$group" ]; then ++ addgroup -g "$PGID" "$GROUP" ++ else ++ bashio::log.notice "Re-using existing group with gid $PGID: $group" ++ GROUP="$group" ++ fi + +- supplementary_groups+=( "$group" ) +- done ++ # Replace existing user (ensures correct shell and primary group) ++ user="$(getent passwd "$PUID" | cut -d: -f1 || true)" ++ if [ -n "$user" ]; then ++ bashio::log.notice "Replacing existing user with uid $PUID: $user" ++ deluser "$user" ++ fi ++ adduser -G "$GROUP" -D -u "$PUID" "$USER" + +- bashio::log.info "Appending supplementary groups: ${supplementary_groups[*]}" +- for group in "${supplementary_groups[@]}"; do +- addgroup "$USER" "$group" +- done ++ if [ -n "${EXTRA_GID:-}" ]; then ++ bashio::log.info "Resolving supplementary GIDs: $EXTRA_GID" ++ supplementary_groups=() ++ ++ for gid in $EXTRA_GID; do ++ group="$(getent group "$gid" | cut -d: -f1 || true)" ++ ++ if [ -z "$group" ]; then ++ group="$USER-$gid" ++ addgroup -g "$gid" "$group" ++ fi ++ ++ supplementary_groups+=( "$group" ) ++ done ++ ++ bashio::log.info "Appending supplementary groups: ${supplementary_groups[*]}" ++ for group in "${supplementary_groups[@]}"; do ++ addgroup "$USER" "$group" ++ done ++ fi + fi + + # +@@ -82,8 +85,12 @@ + # + + bashio::log.info "Initializing venv in $VENV_PATH" +-su "$USER" \ +- -c "python3 -m venv --system-site-packages '$VENV_PATH'" ++if [ "$(whoami)" = "homeassistant" ]; then ++ python3 -m venv --system-site-package "$VENV_PATH" ++else ++ su "$USER" \ ++ -c "python3 -m venv --system-site-packages '$VENV_PATH'" ++fi + + # + # Fix permissions +@@ -104,8 +111,12 @@ + export UV_SYSTEM_PYTHON=false + + bashio::log.info "Installing uv into venv" +-uv --version && su "$USER" \ +- -c "uv pip freeze --system|grep ^uv=|xargs uv pip install" ++if [ "$(whoami)" = "homeassistant" ]; then ++ uv --version && uv pip freeze --system|grep ^uv=|xargs uv pip install ++else ++ uv --version && su "$USER" \ ++ -c "uv pip freeze --system|grep ^uv=|xargs uv pip install" ++fi + + bashio::log.info "Setting new \$HOME" + HOME="$( getent passwd "$USER" | cut -d: -f6 )" +@@ -122,6 +133,10 @@ + fi + + bashio::log.info "Starting homeassistant" +-exec \ +- s6-setuidgid "$USER" \ +- python3 -m homeassistant --config "$CONFIG_PATH" ++if [ "$(whoami)" = "homeassistant" ]; then ++ exec python3 -m homeassistant --config "$CONFIG_PATH" ++else ++ exec \ ++ s6-setuidgid "$USER" \ ++ python3 -m homeassistant --config "$CONFIG_PATH" ++fi diff --git a/roles/homeassistant/files/homeassistant-local.pp b/roles/homeassistant/files/homeassistant-local.pp index e3fe854..e202a25 100644 Binary files a/roles/homeassistant/files/homeassistant-local.pp and b/roles/homeassistant/files/homeassistant-local.pp differ diff --git a/roles/homeassistant/files/homeassistant-local.te b/roles/homeassistant/files/homeassistant-local.te index 60f2983..e6b5e2b 100644 --- a/roles/homeassistant/files/homeassistant-local.te +++ b/roles/homeassistant/files/homeassistant-local.te @@ -1,11 +1,12 @@ -module homeassistant-local 1.0; +module homeassistant-local 1.1; require { type container_t; type system_dbusd_var_run_t; type system_dbusd_t; type bluetooth_t; + class dir read; class sock_file write; class unix_stream_socket connectto; class dbus send_msg; @@ -18,4 +19,5 @@ allow bluetooth_t container_t:dbus send_msg; allow container_t bluetooth_t:dbus send_msg; allow container_t system_dbusd_t:dbus send_msg; allow container_t system_dbusd_t:unix_stream_socket connectto; +allow container_t system_dbusd_var_run_t:dir read; allow container_t system_dbusd_var_run_t:sock_file write; diff --git a/roles/homeassistant/handlers/main.yml b/roles/homeassistant/handlers/main.yml index 61fb83a..36f24f6 100644 --- a/roles/homeassistant/handlers/main.yml +++ b/roles/homeassistant/handlers/main.yml @@ -1,5 +1,6 @@ --- - name: Restart homeassistant - ansible.builtin.service: + ansible.builtin.systemd_service: name: homeassistant-container state: restarted + daemon_reload: true diff --git a/roles/homeassistant/meta/main.yml b/roles/homeassistant/meta/main.yml index 305b1b2..34c289c 100644 --- a/roles/homeassistant/meta/main.yml +++ b/roles/homeassistant/meta/main.yml @@ -2,3 +2,4 @@ dependencies: - {role: nginx} - {role: podman} + - {role: udev} diff --git a/roles/homeassistant/tasks/main.yml b/roles/homeassistant/tasks/main.yml index f2f53d1..746b312 100644 --- a/roles/homeassistant/tasks/main.yml +++ b/roles/homeassistant/tasks/main.yml @@ -1,19 +1,71 @@ --- - name: Create group ansible.builtin.group: - name: ha + name: homeassistant - name: Create user ansible.builtin.user: - name: ha + name: homeassistant comment: Podman HomeAssistant - group: ha + group: homeassistant shell: /sbin/nologin +- name: Enable user lingering + ansible.builtin.command: + argv: + - loginctl + - enable-linger + - homeassistant + creates: /var/lib/systemd/linger/homeassistant + - name: Install dependencies ansible.builtin.package: - name: bluez + name: "{{ item }}" state: installed + with_items: + - bluez + - git + - patch + - yamllint + +- name: Get venv support for container + ansible.builtin.git: + dest: /usr/local/src/homeassistant-docker-venv + repo: https://github.com/tribut/homeassistant-docker-venv.git + update: true + version: master + register: git_result + +- name: Create venv support directory + ansible.builtin.file: + path: /usr/local/libexec/homeassistant-docker-venv + state: directory + mode: "0755" + owner: root + group: "{{ ansible_wheel }}" + +- name: Check if venv support script exists + ansible.builtin.stat: + path: /usr/local/libexec/homeassistant-docker-venv/run + changed_when: false + register: stat_result + +- name: Copy venv support script + ansible.builtin.copy: + dest: /usr/local/libexec/homeassistant-docker-venv/run + src: /usr/local/src/homeassistant-docker-venv/run + mode: "0755" + owner: root + group: "{{ ansible_wheel }}" + remote_src: true + when: not stat_result.stat.exists or git_result.changed + +# https://github.com/home-assistant/core/issues/128214 +- name: Patch venv support script + ansible.posix.patch: + dest: /usr/local/libexec/homeassistant-docker-venv/run + src: homeassistant-docker-venv.patch + notify: Restart homeassistant - name: Enable bluetooth services ansible.builtin.service: @@ -25,7 +77,7 @@ ansible.builtin.copy: dest: /usr/local/share/selinux/homeassistant-local.pp src: homeassistant-local.pp - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" @@ -52,13 +104,28 @@ setype: container_file_t when: ansible_selinux_python_present +- name: Allow podman to use devices + ansible.posix.seboolean: + name: container_use_devices + state: true + persistent: true + +- name: Allow homeassistant to connect specific devices + ansible.builtin.copy: + dest: /etc/udev/rules.d/99-homeassistant.rules + src: 99-homeassistant.rules + mode: "0644" + owner: root + group: "{{ ansible_wheel }}" + notify: Reload udev rules + - name: Create config directory ansible.builtin.file: path: /export/homeassistant state: directory - mode: 0700 - owner: ha - group: ha + mode: "0700" + owner: homeassistant + group: homeassistant setype: _default - name: Link config directory @@ -72,18 +139,49 @@ - name: Copy authentication command ansible.builtin.copy: - dest: /srv/homeassistant/auth-command.sh - src: auth-command.sh - mode: 0755 + dest: /srv/homeassistant/auth-command.py + src: auth-command.py + mode: "0755" owner: root group: "{{ ansible_wheel }}" setype: _default +- name: Create directories for custom integrations + ansible.builtin.file: + path: "{{ item }}" + state: directory + mode: "0755" + owner: root + group: "{{ ansible_wheel }}" + setype: _default + with_items: + - /srv/homeassistant/custom_components + - /srv/homeassistant/downloads + +- name: Download extra integrations + ansible.builtin.git: + dest: "/srv/homeassistant/downloads/{{ item.name }}" + repo: "{{ item.repo }}" + update: true + version: "{{ item.version }}" + notify: Restart homeassistant + with_items: "{{ homeassistant_integrations | default([]) }}" + +- name: Link extra integrations + ansible.builtin.file: + dest: "/srv/homeassistant/custom_components/{{ item.name }}" + src: "../downloads/{{ item.name }}/custom_components/{{ item.name }}" + state: link + owner: root + group: "{{ ansible_wheel }}" + follow: false + with_items: "{{ homeassistant_integrations | default([]) }}" + - name: Create service file ansible.builtin.template: dest: /etc/systemd/system/homeassistant-container.service src: homeassistant-container.service.j2 - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" notify: Restart homeassistant @@ -99,9 +197,9 @@ dest: "/etc/nginx/conf.d/{{ inventory_hostname }}/homeassistant.conf" content: | location / { - proxy_pass http://127.0.0.1:8001; + proxy_pass http://127.0.0.1:8008; } - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" notify: Restart nginx diff --git a/roles/homeassistant/templates/homeassistant-container.service.j2 b/roles/homeassistant/templates/homeassistant-container.service.j2 index 8c83714..a22c105 100644 --- a/roles/homeassistant/templates/homeassistant-container.service.j2 +++ b/roles/homeassistant/templates/homeassistant-container.service.j2 @@ -4,14 +4,19 @@ Wants=network-online.target After=network-online.target [Service] -User=ha +User=homeassistant ExecStart=/usr/bin/podman run \ - --rm -p 127.0.0.1:8001:8123 \ + --rm -p 127.0.0.1:8008:8123 \ --name homeassistant \ + --env PGID=1000 \ + --env PUID=1000 \ --env TZ=Europe/Helsinki \ + --env UMASK=007 \ --userns keep-id \ + --device /dev/ttyUSB0 \ --volume /run/dbus:/run/dbus:ro \ --volume /srv/homeassistant:/config:rw \ + --volume /usr/local/libexec/homeassistant-docker-venv/run:/etc/services.d/home-assistant/run:ro \ docker.io/homeassistant/home-assistant:{{ homeassistant_version }} ExecStop=/usr/bin/podman stop --ignore homeassistant ExecStopPost=/usr/bin/podman rm -f --ignore homeassistant diff --git a/roles/ifstated/tasks/main.yml b/roles/ifstated/tasks/main.yml index 6dc9181..ec548b0 100644 --- a/roles/ifstated/tasks/main.yml +++ b/roles/ifstated/tasks/main.yml @@ -3,7 +3,7 @@ ansible.builtin.template: dest: /etc/ifstated.conf src: "{{ ifstated_config }}" - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" # validate: "ifstated -n -f %s" diff --git a/roles/ifstated/templates/ifstated-dna.conf.j2 b/roles/ifstated/templates/ifstated-dna.conf.j2 index 7fcbd5f..ed794f3 100644 --- a/roles/ifstated/templates/ifstated-dna.conf.j2 +++ b/roles/ifstated/templates/ifstated-dna.conf.j2 @@ -17,10 +17,9 @@ state master { init { # spoof mac to keep dhcp lease in sync with both gw's run "/sbin/ifconfig vio1 lladdr {{ gw_home_mac }} up" - # flush routes and run dhclient and dhcpcd + # flush routes and renew lease run "/sbin/route -qn flush" - run "/sbin/dhclient vio1" - #run "/sbin/rcctl restart dhcpcd > /dev/null" + run "/usr/sbin/dhcpleasectl vio1" # reset firewall rules run "sleep 5 ; pfctl -f /etc/pf.conf" } @@ -31,8 +30,6 @@ state master { state backup { init { - # kill dhclient (TODO: better command for this) - run "pkill -9 dhclient" # bring down interface and reset mac run "/sbin/ifconfig vio1 delete lladdr {{ gw_home_mac }} down" # flush routes and fix default route diff --git a/roles/influxdb/meta/main.yml b/roles/influxdb/meta/main.yml index b95ceec..954fabd 100644 --- a/roles/influxdb/meta/main.yml +++ b/roles/influxdb/meta/main.yml @@ -1,3 +1,3 @@ --- dependencies: - - {role: nginx/server} + - {role: nginx} diff --git a/roles/influxdb/tasks/main.yml b/roles/influxdb/tasks/main.yml index 90d8046..f77db0b 100644 --- a/roles/influxdb/tasks/main.yml +++ b/roles/influxdb/tasks/main.yml @@ -38,7 +38,7 @@ ansible.builtin.file: path: /etc/logrotate.d/influxdb state: file - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" @@ -46,7 +46,7 @@ ansible.builtin.file: path: /export/influxdb state: directory - mode: 0750 + mode: "0750" owner: influxdb group: influxdb @@ -63,7 +63,7 @@ ansible.builtin.copy: dest: /etc/influxdb/config.toml src: config.toml - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" notify: Restart influxdb @@ -87,7 +87,7 @@ location / { proxy_pass http://127.0.0.1:8086/; } - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" notify: Restart nginx diff --git a/roles/ipsilon/README.md b/roles/ipsilon/README.md new file mode 100644 index 0000000..5e29d18 --- /dev/null +++ b/roles/ipsilon/README.md @@ -0,0 +1,28 @@ +== Creating openidc key == + +Create two rsa keys: +``` +openssl genrsa -out signing.key 4096 +openssl genrsa -out encryption.key 4096 +``` + +Create JWK keys: +``` +python3 -c ' +from datetime import datetime +from jwcrypto.jwk import JWK, JWKSet +keyset = JWKSet() +date = datetime.now().strftime("%Y%m%d") +with open("./signing.key", "r") as key: + jwkkey = JWK.from_pem(key.read().encode("UTF-8")) + jwkkey.update(use="sig") + jwkkey.update(kid=f"{date}-sig") + keyset.add(jwkkey) +with open("./encryption.key", "r") as key: + jwkkey = JWK.from_pem(key.read().encode("UTF-8")) + jwkkey.update(use="enc") + jwkkey.update(kid=f"{date}-enc") + keyset.add(jwkkey) +print(keyset.export()) +' +``` diff --git a/roles/ipsilon/handlers/main.yml b/roles/ipsilon/handlers/main.yml new file mode 100644 index 0000000..072010a --- /dev/null +++ b/roles/ipsilon/handlers/main.yml @@ -0,0 +1,18 @@ +--- +- name: Rebuild ipsilon-container + ansible.builtin.command: + argv: + - podman + - build + - -t + - ipsilon + - /usr/local/src/docker-ipsilon + become: true + become_user: ipsilon + notify: Restart ipsilon-container + +- name: Restart ipsilon-container + ansible.builtin.systemd: + name: ipsilon-container + daemon_reload: true + state: restarted diff --git a/roles/ipsilon/meta/main.yml b/roles/ipsilon/meta/main.yml new file mode 100644 index 0000000..b8e2a3e --- /dev/null +++ b/roles/ipsilon/meta/main.yml @@ -0,0 +1,5 @@ +--- +dependencies: + - {role: git} + - {role: nginx} + - {role: podman} diff --git a/roles/ipsilon/tasks/main.yml b/roles/ipsilon/tasks/main.yml new file mode 100644 index 0000000..c82bcd1 --- /dev/null +++ b/roles/ipsilon/tasks/main.yml @@ -0,0 +1,128 @@ +--- +- name: Create group + ansible.builtin.group: + name: ipsilon + +- name: Create user + ansible.builtin.user: + name: ipsilon + comment: Podman Ipsilon + group: ipsilon + shell: /sbin/nologin + +- name: Enable user lingering + ansible.builtin.command: + argv: + - loginctl + - enable-linger + - ipsilon + creates: /var/lib/systemd/linger/ipsilon + +- name: Copy host key + ansible.builtin.copy: + dest: "{{ tls_private }}/ipsilon.key" + src: "{{ tls_private }}/{{ inventory_hostname }}.key" + mode: "0640" + owner: root + group: ipsilon + remote_src: true + +- name: Copy OIDC key + ansible.builtin.copy: + dest: "{{ tls_private }}/openidc.key" + src: "{{ ansible_private }}/files/ipsilon/openidc.key" + mode: "0640" + owner: root + group: ipsilon + notify: Restart ipsilon-container + +- name: Fix SELinux contexts from config directory + community.general.sefcontext: + path: /etc/ipsilon(/.*)? + setype: container_file_t + when: ansible_selinux_python_present + +- name: Get subuid number + ansible.builtin.command: + argv: + - awk + - "-F:" + - '{ if ($1 == "ipsilon") print $2 + 899 }' + - /etc/subuid + changed_when: false + register: subuid + +- name: Get subgid number + ansible.builtin.command: + argv: + - awk + - "-F:" + - '{ if ($1 == "ipsilon") print $2 + 899 }' + - /etc/subgid + changed_when: false + register: subgid + +- name: Create config directory + ansible.builtin.file: + path: /etc/ipsilon + state: directory + mode: "0750" + owner: root + group: ipsilon + setype: _default + +- name: Create OIDC static config + ansible.builtin.template: + dest: /etc/ipsilon/openidc-static.conf + src: openidc-static.conf.j2 + mode: "0600" + owner: "{{ subuid.stdout }}" + group: "{{ subgid.stdout }}" + setype: _default + notify: Restart ipsilon-container + +- name: Get container source + ansible.builtin.git: + dest: /usr/local/src/docker-ipsilon + repo: https://github.com/foo-sh/docker-ipsilon.git + update: true + version: master + notify: Rebuild ipsilon-container + +- name: Create service file + ansible.builtin.template: + dest: /etc/systemd/system/ipsilon-container.service + src: ipsilon-container.service.j2 + mode: "0644" + owner: root + group: "{{ ansible_wheel }}" + notify: Restart ipsilon-container + +- name: Create service config + ansible.builtin.template: + dest: /etc/sysconfig/ipsilon-container + src: ipsilon-container.sysconfig.j2 + mode: "0600" + owner: root + group: "{{ ansible_wheel }}" + notify: Restart ipsilon-container + +- name: Enable service + ansible.builtin.service: + name: ipsilon-container + state: started + enabled: true + +- name: Copy nginx config + ansible.builtin.copy: + dest: "/etc/nginx/conf.d/{{ inventory_hostname }}/ipsilon-container.conf" + content: | + location /ipsilon { + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Host idp.foo.sh; + proxy_pass http://127.0.0.1:8011/; + } + mode: "0644" + owner: root + group: "{{ ansible_wheel }}" + notify: Restart nginx diff --git a/roles/ipsilon/templates/ipsilon-container.service.j2 b/roles/ipsilon/templates/ipsilon-container.service.j2 new file mode 100644 index 0000000..2c08f94 --- /dev/null +++ b/roles/ipsilon/templates/ipsilon-container.service.j2 @@ -0,0 +1,23 @@ +[Unit] +Description=Ipsilon Container +Wants=network-online.target +After=network-online.target + +[Service] +User=ipsilon +EnvironmentFile=/etc/sysconfig/ipsilon-container +ExecStart=/usr/bin/podman run \ + --rm -p 127.0.0.1:8011:80 \ + --name ipsilon \ + --env LDAP_* --env IPSILON_*\ + --volume={{ tls_certs }}/ca.crt:/etc/pki/tls/certs/ca.crt:ro \ + --volume={{ tls_certs }}/{{ inventory_hostname }}.crt:/etc/pki/tls/certs/{{ inventory_hostname }}.crt:ro \ + --volume={{ tls_private }}/ipsilon.key:/etc/pki/tls/private/{{ inventory_hostname }}.key:ro \ + --volume={{ tls_private }}/openidc.key:/etc/ipsilon/openidc.key:ro \ + --volume=/etc/ipsilon/openidc-static.conf:/etc/ipsilon/root/openidc-static.conf:rw \ + ipsilon:latest +ExecStop=/usr/bin/podman stop --ignore ipsilon +ExecStopPost=/usr/bin/podman rm -f --ignore ipsilon + +[Install] +WantedBy=multi-user.target diff --git a/roles/ipsilon/templates/ipsilon-container.sysconfig.j2 b/roles/ipsilon/templates/ipsilon-container.sysconfig.j2 new file mode 100644 index 0000000..4150eaf --- /dev/null +++ b/roles/ipsilon/templates/ipsilon-container.sysconfig.j2 @@ -0,0 +1,11 @@ +LDAP_BASEDN="{{ ldap_basedn }}" +LDAP_BINDPW="{{ ipsilon_ldap_pass }}" +IPSILON_DB_USER="ipsilon" +IPSILON_DB_PASS="{{ ipsilon_mysql_pass }}" +IPSILON_DB_HOST="sqldb02.home.foo.sh" +IPSILON_DB_CA="{{ tls_certs }}/ca.crt" +IPSILON_DB_KEY="{{ tls_private }}/{{ inventory_hostname }}.key" +IPSILON_DB_CERT="{{ tls_certs }}/{{ inventory_hostname}}.crt" +IPSILON_HOSTNAME="idp.foo.sh" +IPSILON_OPENIDC_KEYID="{{ ipsilon_openidc_keyid }}" +IPSILON_OPENIDC_SALT="{{ ipsilon_openidc_salt }}" diff --git a/roles/ipsilon/templates/openidc-static.conf.j2 b/roles/ipsilon/templates/openidc-static.conf.j2 new file mode 100644 index 0000000..f6bb88d --- /dev/null +++ b/roles/ipsilon/templates/openidc-static.conf.j2 @@ -0,0 +1,26 @@ +[client] +{% for client in openidc_clients %} +{{ client["name"] }} application_type="web" +{{ client["name"] }} client_id=null +{{ client["name"] }} client_id_issued_at=0 +{{ client["name"] }} client_name="{{ client["name"] }}" +{{ client["name"] }} client_secret="{{ client["client_secret"] }}" +{{ client["name"] }} client_secret_expires_at=0 +{{ client["name"] }} client_uri="{{ client["client_uri"] }}" +{{ client["name"] }} contacts=["adm@foo.sh"] +{{ client["name"] }} grant_types=["authorization_code"] +{{ client["name"] }} id_token_signed_response_alg="RS256" +{{ client["name"] }} ipsilon_internal={"type": "static", "client_id": "{{ client["name"] }}", "trusted": true} +{{ client["name"] }} jwks=null +{{ client["name"] }} jwks_uri=null +{{ client["name"] }} logo_uri=null +{{ client["name"] }} policy_uri=null +{{ client["name"] }} redirect_uris={{ client["redirect_uris"] | ansible.builtin.to_json }} +{{ client["name"] }} request_uris=[] +{{ client["name"] }} require_auth_time=null +{{ client["name"] }} response_types=["code"] +{{ client["name"] }} subject_type="pairwise" +{{ client["name"] }} sector_identifier_uri=null +{{ client["name"] }} token_endpoint_auth_method="{{ client["token_endpoint_auth_method"] | default("client_secret_post") }}" +{{ client["name"] }} tos_uri=null +{% endfor %} diff --git a/roles/iptables/tasks/main.yml b/roles/iptables/tasks/main.yml index aa52ce5..f01888c 100644 --- a/roles/iptables/tasks/main.yml +++ b/roles/iptables/tasks/main.yml @@ -16,7 +16,7 @@ ansible.builtin.template: src: "{{ item }}.j2" dest: "/etc/sysconfig/{{ item }}" - mode: 0600 + mode: "0600" owner: root group: root notify: "Reload {{ item }}" diff --git a/roles/kadmin/tasks/main.yml b/roles/kadmin/tasks/main.yml index 3b8ccc1..447b344 100644 --- a/roles/kadmin/tasks/main.yml +++ b/roles/kadmin/tasks/main.yml @@ -11,7 +11,7 @@ ansible.builtin.template: dest: /var/kerberos/krb5kdc/kdc.conf src: kdc.conf.j2 - mode: 0600 + mode: "0600" owner: root group: "{{ ansible_wheel }}" diff --git a/roles/kdc/tasks/main.yml b/roles/kdc/tasks/main.yml index a2dcd3b..f7ef8eb 100644 --- a/roles/kdc/tasks/main.yml +++ b/roles/kdc/tasks/main.yml @@ -10,11 +10,19 @@ group: kdc shell: /sbin/nologin +- name: Enable user lingering + ansible.builtin.command: + argv: + - loginctl + - enable-linger + - kdc + creates: /var/lib/systemd/linger/kdc + - name: Get container source ansible.builtin.git: dest: /usr/local/src/docker-kdc repo: https://github.com/foo-sh/docker-kdc.git - update: false + update: true version: main notify: Rebuild kdc-container @@ -22,7 +30,7 @@ ansible.builtin.template: dest: /etc/sysconfig/kdc-container src: kdc-container.sysconfig.j2 - mode: 0600 + mode: "0600" owner: root group: "{{ ansible_wheel }}" @@ -30,7 +38,7 @@ ansible.builtin.copy: dest: /etc/systemd/system/kdc-container.service src: kdc-container.service - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" @@ -47,7 +55,7 @@ location /KdcProxy { proxy_pass http://127.0.0.1:8001; } - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" notify: Restart nginx diff --git a/roles/keytab/defaults/main.yml b/roles/keytab/defaults/main.yml index 8b08f0a..e4c4ebf 100644 --- a/roles/keytab/defaults/main.yml +++ b/roles/keytab/defaults/main.yml @@ -1,3 +1,3 @@ --- -keytab: /etc/krb5.keytab -group: "{{ ansible_wheel }}" +keytab_path: /etc/krb5.keytab +keytab_group: "{{ ansible_wheel }}" diff --git a/roles/keytab/files/empty.keytab b/roles/keytab/files/empty.keytab new file mode 100644 index 0000000..2e2a96a --- /dev/null +++ b/roles/keytab/files/empty.keytab @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/roles/keytab/tasks/main.yml b/roles/keytab/tasks/main.yml index c4e5496..ef83269 100644 --- a/roles/keytab/tasks/main.yml +++ b/roles/keytab/tasks/main.yml @@ -1,50 +1,61 @@ --- - name: Check if keytab exists ansible.builtin.stat: - path: "{{ keytab }}" + path: "{{ keytab_path }}" register: keytab_status check_mode: false -- name: Add principal to keytab - ansible.builtin.command: - argv: - - kadmin.local - - -x - - host=ldaps://ldap01.foo.sh - - ktadd - - -k - - "/tmp/{{ inventory_hostname }}.kt" - - "{{ item }}" - with_items: "{{ principals }}" - delegate_to: ldap01.home.foo.sh - when: not keytab_status.stat.exists +- name: Create keytab + block: + - name: Create temporary file + ansible.builtin.tempfile: + state: file + register: tempfile -- name: Get keytab - ansible.builtin.command: - argv: - - base64 - - "/tmp/{{ inventory_hostname }}.kt" - register: keytab_data - delegate_to: ldap01.home.foo.sh - when: not keytab_status.stat.exists + - name: Initialize keytab + ansible.builtin.copy: + dest: "{{ tempfile.path }}" + src: empty.keytab + mode: "0600" + owner: root + group: "{{ ansible_wheel }}" -- name: Delete temporary file - ansible.builtin.file: - path: "/tmp/{{ inventory_hostname }}.kt" - state: absent - delegate_to: ldap01.home.foo.sh + - name: Add principal to keytab + ansible.builtin.command: + argv: + - kadmin.local + - -x + - host=ldaps://ldap01.foo.sh + - ktadd + - -k + - "{{ tempfile.path }}" + - "{{ item }}" + with_items: "{{ keytab_principals }}" + + - name: Get keytab + ansible.builtin.command: + argv: + - base64 + - "{{ tempfile.path }}" + register: keytab_data + + - name: Delete temporary file + ansible.builtin.file: + path: "{{ tempfile.path }}" + state: absent when: not keytab_status.stat.exists + delegate_to: ldap01.home.foo.sh - name: Deploy keytab file ansible.builtin.shell: >- set -o pipefail && umask 077 && - echo '{{ keytab_data.stdout }}' | base64 -d > "{{ keytab }}" + echo '{{ keytab_data.stdout }}' | base64 -d > "{{ keytab_path }}" when: not keytab_status.stat.exists - name: Check keytab permissions ansible.builtin.file: - path: "{{ keytab }}" - mode: "{% if group == ansible_wheel %}0600{% else %}0640{% endif %}" + path: "{{ keytab_path }}" + mode: "{% if keytab_group == ansible_wheel %}0600{% else %}0640{% endif %}" owner: root - group: "{{ group }}" + group: "{{ keytab_group }}" diff --git a/roles/kvm_host/files/check-orphaned-vm.sh b/roles/kvm_host/files/check-orphaned-vm.sh new file mode 100755 index 0000000..43954e1 --- /dev/null +++ b/roles/kvm_host/files/check-orphaned-vm.sh @@ -0,0 +1,24 @@ +#!/bin/sh + +set -eu + +# check that all vm's are in ldap +virsh list --all --name | while read -r vm ; do + [ "$vm" = "" ] && continue + if ! ldapsearch -LLL "(&(cn=${vm})(objectClass=device))" dn 2> /dev/null | \ + grep -qE "^dn: cn=${vm},ou=Hosts," + then + echo "WARNING: Host \"${vm}\" registered in KVM but not in LDAP" 1>62 + fi +done + +# check that all disks have owner +for dir in /srv/libvirt/{hdd,nvme,os,ssd} ; do + [ -d "$dir" ] || continue + find "$dir" -name \*.img | while read -r image ; do + vm="$(basename "$image" ".img" | sed -e 's/\.[a-z]$//')" + if ! virsh dominfo "$vm" > /dev/null 2>&1 ; then + echo "WARNING: Orphaned disk image \"${image}\" found" 1>&2 + fi + done +done diff --git a/roles/kvm_host/meta/main.yml b/roles/kvm_host/meta/main.yml new file mode 100644 index 0000000..d2f9d51 --- /dev/null +++ b/roles/kvm_host/meta/main.yml @@ -0,0 +1,3 @@ +--- +dependencies: + - {role: ldap} diff --git a/roles/kvm_host/tasks/main.yml b/roles/kvm_host/tasks/main.yml index bafddde..78ea78e 100644 --- a/roles/kvm_host/tasks/main.yml +++ b/roles/kvm_host/tasks/main.yml @@ -7,7 +7,7 @@ blacklist bluetooth blacklist btintel blacklist btusb - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" @@ -29,13 +29,15 @@ ansible.builtin.file: path: "{{ item }}" state: directory - mode: 0770 + mode: "0770" owner: root group: qemu with_items: - /export/libvirt - /export/libvirt/hdd + - /export/libvirt/nvme - /export/libvirt/ssd + - /export/libvirt/os - name: Link data directory ansible.builtin.file: @@ -51,3 +53,18 @@ name: libvirtd state: started enabled: true + +- name: Install script for checking orphaned vm's + ansible.builtin.copy: + dest: /usr/local/bin/check-orphaned-vm + src: check-orphaned-vm.sh + mode: "0755" + owner: root + group: "{{ ansible_wheel }}" + +- name: Add cronjob to check orphaned vm's + ansible.builtin.cron: + name: check-orphaned-vm + hour: "5" + minute: "5" + job: /usr/local/bin/check-orphaned-vm diff --git a/roles/ldap_gravatar/tasks/main.yml b/roles/ldap_gravatar/tasks/main.yml index ea21621..ee61b2d 100644 --- a/roles/ldap_gravatar/tasks/main.yml +++ b/roles/ldap_gravatar/tasks/main.yml @@ -11,7 +11,7 @@ ansible.builtin.copy: src: gravatar-update.py dest: /usr/local/sbin/gravatar-update - mode: 0755 + mode: "0755" owner: root group: "{{ ansible_wheel }}" diff --git a/roles/ldap_netdb/tasks/main.yml b/roles/ldap_netdb/tasks/main.yml index 53b6d45..11b0275 100644 --- a/roles/ldap_netdb/tasks/main.yml +++ b/roles/ldap_netdb/tasks/main.yml @@ -12,7 +12,7 @@ ansible.builtin.copy: src: netdb-update.py dest: /usr/local/sbin/netdb-update - mode: 0755 + mode: "0755" owner: root group: "{{ ansible_wheel }}" diff --git a/roles/ldap_server/defaults/main.yml b/roles/ldap_server/defaults/main.yml index 3454578..0563395 100644 --- a/roles/ldap_server/defaults/main.yml +++ b/roles/ldap_server/defaults/main.yml @@ -5,3 +5,4 @@ ldap_datadir: >- {% if ansible_local['export'] %}/export{% else %}/srv{% endif %}/ldap ldap_backupdir: >- {% if ansible_local['export'] -%}/export{% else -%}/srv{% endif -%}/backup +ldap_master: false diff --git a/roles/ldap_server/files/ldap-backup.sh b/roles/ldap_server/files/ldap-backup.sh index 7942743..2e84891 100755 --- a/roles/ldap_server/files/ldap-backup.sh +++ b/roles/ldap_server/files/ldap-backup.sh @@ -12,23 +12,24 @@ if [ "$(whoami)" != "root" ]; then fi BACKUPDIR="/srv/backup" -BACKUPAGE="7" +BACKUPAGE="30" DATE="$(date '+%Y-%m-%d')" +cd "$BACKUPDIR" + ldapsearch -LLL -x -H ldapi:// -s base -b 'cn=Databases,cn=Monitor' \ '(objectClass=*)' namingContexts | \ sed -n 's/^namingContexts: \(.*\)/\1/p' | while read -r db ; do - [ "${db}" = "cn=config" ] && continue - if ! slapcat -f /etc/openldap/slapd.conf -b "${db}" 2> /dev/null | \ - gzip > "${BACKUPDIR}/${db}.${DATE}.gz" ; then + [ "$db" = "cn=config" ] && continue + if ! slapcat -f /etc/openldap/slapd.conf -b "$db" 2> /dev/null | \ + gzip > "${db}.${DATE}.gz" + then echo "ERR: Failed to backup database ${db}" 1>&2 continue fi chgrp backup "${BACKUPDIR}/${db}.${DATE}.gz" done -cd ${BACKUPDIR} && { - find . -xdev -depth -mindepth 1 -maxdepth 1 -type f -mtime +${BACKUPAGE} \ - -name '*.gz' -execdir rm -f -- {} \; -} +find . -xdev -depth -mindepth 1 -maxdepth 1 -type f -mtime +${BACKUPAGE} \ + -name '*.gz' -execdir rm -f -- {} \; diff --git a/roles/ldap_server/meta/main.yml b/roles/ldap_server/meta/main.yml index e59e67d..84aca43 100644 --- a/roles/ldap_server/meta/main.yml +++ b/roles/ldap_server/meta/main.yml @@ -1,5 +1,6 @@ --- dependencies: + - {role: backup_base} - {role: kerberos} - {role: ldap} - {role: saslauthd} diff --git a/roles/ldap_server/tasks/main.yml b/roles/ldap_server/tasks/main.yml index c7e54a4..834ac03 100644 --- a/roles/ldap_server/tasks/main.yml +++ b/roles/ldap_server/tasks/main.yml @@ -39,7 +39,7 @@ ansible.builtin.file: path: "{{ ldap_datadir }}" state: directory - mode: 0700 + mode: "0700" owner: ldap group: ldap seuser: _default @@ -48,44 +48,18 @@ - name: Link LDAP data directory ansible.builtin.file: path: /srv/ldap - src: /export/ldap + src: "{{ ldap_datadir }}" state: link owner: root group: root follow: false when: ldap_datadir != "/srv/ldap" -- name: Import sftpuser role - ansible.builtin.import_role: - name: sftpuser - vars: - chroot: /srv/backup - user: backup - publickeys: "{{ backup_publickeys }}" - -- name: Create backup directory - ansible.builtin.file: - path: "{{ ldap_backupdir }}" - state: directory - mode: 0750 - owner: root - group: backup - -- name: Link backup directory - ansible.builtin.file: - path: /srv/backup - src: /export/backup - state: link - owner: root - group: "{{ ansible_wheel }}" - follow: false - when: ldap_backupdir != "/srv/backup" - - name: Copy backup script ansible.builtin.copy: dest: /usr/local/sbin/ldap-backup src: ldap-backup.sh - mode: 0755 + mode: "0755" owner: root group: "{{ ansible_wheel }}" @@ -101,7 +75,7 @@ ansible.builtin.copy: dest: /usr/local/sbin/ldapspn src: ldapspn.py - mode: 0755 + mode: "0755" owner: root group: "{{ ansible_wheel }}" when: ldap_master is defined @@ -121,7 +95,7 @@ dest: /etc/sasl2/slapd.conf content: | pwcheck_method: saslauthd - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" notify: Restart slapd @@ -130,7 +104,7 @@ ansible.builtin.copy: dest: "{{ tls_certs }}/{{ ldap_server_cert }}.crt" src: "/srv/letsencrypt/live/{{ ldap_server_cert }}/cert.pem" - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" tags: certificates @@ -140,7 +114,7 @@ ansible.builtin.copy: dest: "{{ tls_private }}/{{ ldap_server_cert }}.key" src: "/srv/letsencrypt/live/{{ ldap_server_cert }}/privkey.pem" - mode: 0640 + mode: "0640" owner: root group: ldap tags: certificates @@ -150,7 +124,7 @@ ansible.builtin.copy: dest: "{{ tls_certs }}/{{ ldap_server_cert }}-chain.crt" src: "/srv/letsencrypt/live/{{ ldap_server_cert }}/chain.pem" - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" tags: certificates @@ -168,6 +142,7 @@ delegate_to: localhost register: result changed_when: false + check_mode: false tags: certificates - name: Link server chain certificate @@ -193,7 +168,7 @@ ansible.builtin.file: path: /etc/systemd/system/slapd.service.d state: directory - mode: 0755 + mode: "0755" owner: root group: "{{ ansible_wheel }}" when: ansible_distribution == "Rocky" @@ -202,7 +177,7 @@ ansible.builtin.copy: dest: /etc/systemd/system/slapd.service.d/local.conf src: slapd.service - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" notify: Restart slapd @@ -212,7 +187,7 @@ ansible.builtin.copy: dest: /etc/sysconfig/slapd src: slapd.sysconfig - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" notify: Restart slapd @@ -222,7 +197,7 @@ ansible.builtin.copy: dest: "/etc/openldap/schema/{{ item }}" src: "{{ item }}" - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" with_items: @@ -237,7 +212,7 @@ ansible.builtin.copy: dest: /etc/openldap/check_password.conf src: check_password.conf - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" @@ -245,7 +220,7 @@ ansible.builtin.template: dest: /etc/openldap/slapd.conf src: slapd.conf.j2 - mode: 0640 + mode: "0640" owner: root group: ldap notify: Restart slapd @@ -272,6 +247,6 @@ ansible.builtin.copy: dest: /etc/openldap/slapd.keytab src: "{{ ansible_private }}/files/keytabs/slapd.keytab" - mode: 0640 + mode: "0640" owner: root group: ldap diff --git a/roles/ldap_server/templates/slapd.conf.j2 b/roles/ldap_server/templates/slapd.conf.j2 index 903639c..98efbea 100644 --- a/roles/ldap_server/templates/slapd.conf.j2 +++ b/roles/ldap_server/templates/slapd.conf.j2 @@ -88,7 +88,7 @@ memberof-memberof-ad memberOf # access without access to clear text data directory /srv/ldap -{% if ldap_master is not defined %} +{% if not ldap_master %} # replication syncrepl rid={{ 999 | random(seed=inventory_hostname) }} provider=ldaps://ldap01.foo.sh @@ -139,6 +139,10 @@ authz-regexp "uid=([^.]\+),cn=login,cn=auth" "ldap:///{{ ldap_basedn }}??sub?(&(uid=$1)(objectClass=posixAccount))" +# allow everyone to read root object +access to dn.base={{ ldap_basedn }} + by * read + # require authentication for authenticated users that don't match above access to * by dn.children="cn=peercred,cn=external,cn=auth" auth diff --git a/roles/lm_sensors/handlers/main.yml b/roles/lm_sensors/handlers/main.yml deleted file mode 100644 index ea6cb47..0000000 --- a/roles/lm_sensors/handlers/main.yml +++ /dev/null @@ -1,8 +0,0 @@ ---- -- name: Run sensors-detect - ansible.builtin.shell: "cat /dev/null | sensors-detect" - -- name: Restart lm_sensors - ansible.builtin.service: - name: lm_sensors - state: restarted diff --git a/roles/lm_sensors/tasks/main.yml b/roles/lm_sensors/tasks/main.yml deleted file mode 100644 index 9231b53..0000000 --- a/roles/lm_sensors/tasks/main.yml +++ /dev/null @@ -1,12 +0,0 @@ ---- -- name: Install packages - ansible.builtin.package: - name: lm_sensors - state: installed - notify: Run sensors-detect - -- name: Enable service - ansible.builtin.service: - name: lm_sensors - state: started - enabled: true diff --git a/roles/mariadb/files/local.cnf b/roles/mariadb/files/local.cnf new file mode 100644 index 0000000..cedabc6 --- /dev/null +++ b/roles/mariadb/files/local.cnf @@ -0,0 +1,4 @@ +[mariadb] +innodb_file_per_table = ON +general_log +general_log_file = /var/log/mariadb/mariadb-query.log diff --git a/roles/mariadb/files/mariadb-backup.sh b/roles/mariadb/files/mariadb-backup.sh index e2181bb..9a4a354 100755 --- a/roles/mariadb/files/mariadb-backup.sh +++ b/roles/mariadb/files/mariadb-backup.sh @@ -4,23 +4,17 @@ set -eu umask 027 -DESTDIR="/export/backup" +DESTDIR="/srv/backup" DATE="$(date +%Y-%m-%d)" -if [ ! -d "$DESTDIR" ]; then - echo "ERR: MariaDB backup directory [${DESTDIR}] does not exist" 1>&2 - exit 1 -fi +cd "$DESTDIR" +find . -xdev -mindepth 2 -maxdepth 2 -type f -mtime +30 \ + -execdir rm -f -- {} \; +find . -xdev -depth -mindepth 1 -maxdepth 1 -type d -empty \ + -execdir rmdir -- {} \; -cd "$DESTDIR" && { - find . -xdev -mindepth 2 -maxdepth 2 -type f -mtime +7 \ - -execdir rm -f -- {} \; - find . -xdev -depth -mindepth 1 -maxdepth 1 -type d -empty \ - -execdir rmdir -- {} \; -} - -DESTDIR="${DESTDIR}/${DATE}" -mkdir "$DESTDIR" +mkdir -m 2770 "$DATE" +chgrp backup "$DATE" for db in $(mysql -e "show databases" -s) ; do case "$db" in @@ -28,5 +22,5 @@ for db in $(mysql -e "show databases" -s) ; do continue ;; esac - mysqldump -E --add-drop-table "$db" | gzip > "${DESTDIR}/${db}.${DATE}.gz" + mysqldump -E --add-drop-table "$db" | gzip > "${DATE}/${db}.${DATE}.gz" done diff --git a/roles/mariadb/files/mariadb-querylog.logrotate b/roles/mariadb/files/mariadb-querylog.logrotate new file mode 100644 index 0000000..70002a1 --- /dev/null +++ b/roles/mariadb/files/mariadb-querylog.logrotate @@ -0,0 +1,17 @@ +/var/log/mariadb/mariadb-query.log { + create 600 mysql mysql + su mysql mysql + notifempty + daily + rotate 3 + missingok + compress + sharedscripts + postrotate + # just if mariadbd is really running + if [ -e /run/mariadb/mariadb.pid ] + then + kill -1 $(&2 + exit 1 +fi diff --git a/roles/mariadb/meta/main.yml b/roles/mariadb/meta/main.yml new file mode 100644 index 0000000..f178512 --- /dev/null +++ b/roles/mariadb/meta/main.yml @@ -0,0 +1,3 @@ +--- +dependencies: + - {role: backup_base} diff --git a/roles/mariadb/tasks/main.yml b/roles/mariadb/tasks/main.yml index 519068d..b2a9ca9 100644 --- a/roles/mariadb/tasks/main.yml +++ b/roles/mariadb/tasks/main.yml @@ -16,7 +16,7 @@ ansible.builtin.file: path: /export/mariadb state: directory - mode: 0750 + mode: "0750" owner: mysql group: mysql setype: _default @@ -41,7 +41,7 @@ ansible.builtin.file: path: /etc/mysql state: directory - mode: 0750 + mode: "0750" owner: root group: mysql @@ -56,7 +56,7 @@ ansible.builtin.template: dest: /etc/my.cnf.d/tls.cnf src: tls.cnf.j2 - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" notify: Restart mariadb @@ -64,8 +64,8 @@ - name: Create local configuration ansible.builtin.copy: dest: /etc/my.cnf.d/local.cnf - content: "[mariadb]\ninnodb_file_per_table=ON\n" - mode: 0644 + src: local.cnf + mode: "0644" owner: root group: "{{ ansible_wheel }}" notify: Restart mariadb @@ -91,41 +91,16 @@ ansible.builtin.template: dest: /root/.my.cnf src: my.cnf.j2 - mode: 0600 + mode: "0600" owner: root group: "{{ ansible_wheel }}" when: mariadb_root_password is defined -- name: Import sftpuser role - ansible.builtin.import_role: - name: sftpuser - vars: - chroot: /srv/backup - user: backup - publickeys: "{{ backup_publickeys }}" - -- name: Create backup directory - ansible.builtin.file: - path: /export/backup - state: directory - mode: 02750 - owner: root - group: backup - -- name: Link backup directory - ansible.builtin.file: - path: /srv/backup - src: /export/backup - state: link - owner: root - group: "{{ ansible_wheel }}" - follow: false - - name: Copy backup script ansible.builtin.copy: dest: /usr/local/sbin/mariadb-backup src: mariadb-backup.sh - mode: 0755 + mode: "0755" owner: root group: "{{ ansible_wheel }}" @@ -135,3 +110,26 @@ job: /usr/local/sbin/mariadb-backup hour: "0" minute: "30" + +- name: Add logrotate job for query log + ansible.builtin.copy: + dest: /etc/logrotate.d/mariadb-querylog + src: mariadb-querylog.logrotate + mode: "0644" + owner: root + group: "{{ ansible_wheel }}" + +- name: Copy script to check timezone data + ansible.builtin.copy: + dest: /usr/local/sbin/mysql_tzinfo_check + src: mysql_tzinfo_check.sh + mode: "0755" + owner: root + group: "{{ ansible_wheel }}" + +- name: Create cron job for checking timezone data + ansible.builtin.cron: + name: mysql_tzinfo_check + job: /usr/local/sbin/mysql_tzinfo_check + hour: "3" + minute: "15" diff --git a/roles/mariadb/templates/tls.cnf.j2 b/roles/mariadb/templates/tls.cnf.j2 index e193b3f..7aebd43 100644 --- a/roles/mariadb/templates/tls.cnf.j2 +++ b/roles/mariadb/templates/tls.cnf.j2 @@ -2,3 +2,4 @@ ssl-cert = {{ tls_certs }}/{{ inventory_hostname }}.crt ssl-key = {{ tls_private }}/{{ inventory_hostname }}.key ssl-ca = {{ tls_certs }}/ca.crt +tls_version = TLSv1.3 diff --git a/roles/minecraft/tasks/main.yml b/roles/minecraft/tasks/main.yml index 91f0630..50961a4 100644 --- a/roles/minecraft/tasks/main.yml +++ b/roles/minecraft/tasks/main.yml @@ -7,13 +7,13 @@ - name: Create group ansible.builtin.group: name: minecraft - gid: 1007 + gid: 307 - name: Create user ansible.builtin.user: name: minecraft comment: Service Minecraft - uid: 1007 + uid: 307 group: minecraft create_home: false home: /var/empty @@ -23,7 +23,7 @@ ansible.builtin.file: path: /export/minecraft state: directory - mode: 0750 + mode: "0750" owner: root group: minecraft @@ -40,7 +40,7 @@ ansible.builtin.file: path: "/srv/minecraft/{{ item }}" state: directory - mode: 0770 + mode: "0770" owner: root group: minecraft with_items: @@ -55,7 +55,7 @@ dest: /srv/minecraft/eula.txt content: | eula=true - mode: 0640 + mode: "0640" owner: root group: minecraft @@ -63,7 +63,7 @@ ansible.builtin.copy: dest: /srv/minecraft/server.properties src: server.properties - mode: 0640 + mode: "0640" owner: root group: minecraft @@ -72,7 +72,7 @@ dest: "/srv/minecraft/{{ item }}" content: "[]" force: false - mode: 0660 + mode: "0660" owner: root group: minecraft with_items: @@ -85,7 +85,7 @@ ansible.builtin.file: path: /usr/local/lib/minecraft state: directory - mode: 0755 + mode: "0755" owner: root group: "{{ ansible_wheel }}" @@ -95,7 +95,7 @@ url: >- https://launcher.mojang.com/v1/objects/{{ minecraft_sha1sum }}/server.jar checksum: "sha1:{{ minecraft_sha1sum }}" - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" @@ -103,7 +103,7 @@ ansible.builtin.copy: dest: /etc/systemd/system/minecraft.service src: minecraft.service - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" diff --git a/roles/mirror/base/files/sync-mirrors b/roles/mirror/base/files/sync-mirrors deleted file mode 100755 index ef6100e..0000000 --- a/roles/mirror/base/files/sync-mirrors +++ /dev/null @@ -1,128 +0,0 @@ -#!/bin/bash - -LOCKFILE="/var/run/sync-mirrors/lockfile" -LOGFILE="/var/log/sync-mirrors/sync-mirrors-$(date +%Y%m%d%H%M%S).log" -CONFDIR="/etc/sync-mirrors" - -usage() { - echo "Usage: $(basename "$0") [-v] [mirror]" 1>&2 - echo " $(basename "$0") -l" 1>&2 -} - -logmsg() { - [ "${VERBOSE}" -eq 1 ] && echo "$1" - echo "$(date '+%Y/%m/%d %H:%M:%S') [$$] $1" >> "${LOGFILE}" -} - -if [ -d ${CONFDIR} ]; then - MIRRORLIST="$(find ${CONFDIR}/ -name \*.conf | while read -r f ; \ - do basename "${f}" | sed -e 's/\.conf$//' ; done)" - if [ "${MIRRORLIST}" = "" ]; then - echo "ERR: No configured mirrors found" 1>&2 - exit 1 - fi -else - echo "ERR: Config directory [${CONFDIR}] missing" 1>&2 - exit 1 -fi - -VERBOSE=0 -NOOP="" -EXTRA_OPTS="" -while getopts "vhln" c ; do - case $c in - v) - VERBOSE=1 - EXTRA_OPTS="${EXTRA_OPTS} -v --progress" - ;; - h) - usage - exit 1 - ;; - l) - echo "Available mirrors:" - for name in ${MIRRORLIST} ; do - echo " ${name}" - done - exit 0 - ;; - n) - NOOP=" (DRY RUN)" - EXTRA_OPTS="${EXTRA_OPTS} -n" - ;; - *) - usage - exit 1 - ;; - esac -done - -shift "$((OPTIND - 1))" - -if [ $# -gt 0 ]; then - for mirror in "$@" ; do - if [ ! -f "${CONFDIR}/$1.conf" ]; then - echo "ERR: No mirror named [$1]" 1>&2 - exit 1 - fi - SYNC="${MIRRORS} $1" - shift - done -else - SYNC="${MIRRORLIST}" -fi - -if [ "$(whoami)" != "mirror" ]; then - echo "ERR: Script needs to be run as mirror user" 1>&2 - exit 1 -fi - -umask 022 - -if [ -f "${LOCKFILE}" ]; then - if kill -0 "$(cat ${LOCKFILE})" ; then - STARTED=" ($(stat --format='%y' ${LOCKFILE}))" - echo "ERR: Lockfile exists${STARTED}, exiting" 1>&2 - exit 1 - else - echo "WARN: Removing stale lock file..." 1>&2 - rm -f "${LOCKFILE}" - fi -fi -trap 'rm -f ${LOCKFILE}' INT TERM EXIT -echo "$$" > "${LOCKFILE}" - -for mirror in ${SYNC} ; do - POSTCMD="" - SRC="" - RSYNCOPTS="" - . "${CONFDIR}/${mirror}.conf" - if [ "${SRC}" = "" ]; then - echo "ERR: No SRC set for mirror ${mirror} ..." 1>&2 - exit 1 - fi - logmsg "Starting ${mirror} sync${NOOP}..." - rsync -aH -4 ${EXTRA_OPTS} --numeric-ids --delete --delete-delay \ - --delay-updates --no-motd ${RSYNCOPTS} --log-file="${LOGFILE}" \ - --exclude=.~tmp~/ "${SRC}" "/srv/mirrors/${mirror}/" - STATUS=$? - if [ ${STATUS} -ne 0 ]; then - echo "WARN: Encountered errors on ${mirror} sync, see ${LOGFILE} for details" 1>&2 - fi - logmsg "Finished ${mirror} sync with exit status ${STATUS}${NOOP} ..." - if [ "${POSTCMD}" != "" ]; then - logmsg "Running post for ${mirror} ..." - if [ "${VERBOSE}" -eq 1 ]; then - ${POSTCMD} 2>&1 | tee >( \ - awk "{ print strftime(\"%Y/%m/%d %H:%M:%S\") \" [$$] \" \$0 }" \ - >> "${LOGFILE}" ) - else - ${POSTCMD} 2>&1 | \ - awk "{ print strftime(\"%Y/%m/%d %H:%M:%S\") \" [$$] \" \$0 }" \ - >> "${LOGFILE}" - fi - logmsg "Finished post for ${mirror} ..." - fi -done - -rm -f "${LOCKFILE}" diff --git a/roles/mirror/base/files/sync-mirrors.sh b/roles/mirror/base/files/sync-mirrors.sh new file mode 100755 index 0000000..2dba204 --- /dev/null +++ b/roles/mirror/base/files/sync-mirrors.sh @@ -0,0 +1,125 @@ +#!/bin/sh + +set -eu +umask 022 + +LOCKFILE="/var/run/sync-mirrors/lockfile" +LOGFILE="/var/log/sync-mirrors/sync-mirrors-$(date +%Y%m%d%H%M%S).log" +CONFDIR="/etc/sync-mirrors" + +usage() { + echo "Usage: $(basename "$0") [-v] [mirror]" 1>&2 + echo " $(basename "$0") -l" 1>&2 +} + +list_mirrors() { + for f in "$CONFDIR"/*.conf ; do + basename "$f" ".conf" + done +} + +logmsg() { + "$VERBOSE" && echo "$1" + echo "$(date '+%Y/%m/%d %H:%M:%S') [$$] $1" >> "$LOGFILE" +} + +logstream() { + while read -r line; do + logmsg "$line" + done +} + +if [ ! -d "$CONFDIR" ]; then + echo "ERR: Config directory [${CONFDIR}] missing" 1>&2 + exit 1 +fi + +VERBOSE=false +NOOP="" +EXTRA_OPTS="" +while getopts "vhln" c ; do + case $c in + v) + VERBOSE=true + EXTRA_OPTS="${EXTRA_OPTS} -v --progress" + ;; + h) + usage + exit 0 + ;; + l) + echo "Available mirrors:" + list_mirrors | sed -e 's/^/ /' + exit 0 + ;; + n) + NOOP=" (DRY RUN)" + EXTRA_OPTS="${EXTRA_OPTS} -n" + ;; + *) + usage + exit 1 + ;; + esac +done + +shift "$((OPTIND - 1))" + +if [ $# -eq 0 ]; then + set -- $(list_mirrors) + if [ $# -eq 0 ]; then + echo "ERR: No configured mirrors found" 1>&2 + exit 1 + fi +else + for mirror in "$@" ; do + if [ ! -f "${CONFDIR}/$1.conf" ]; then + echo "ERR: No mirror named [$1]" 1>&2 + exit 1 + fi + done +fi + +if [ "$(whoami)" != "mirror" ]; then + echo "ERR: Script needs to be run as mirror user" 1>&2 + exit 1 +fi + +if [ -f "$LOCKFILE" ]; then + if kill -0 "$(cat $LOCKFILE)" ; then + STARTED=" ($(stat --format='%y' $LOCKFILE))" + echo "ERR: Lockfile exists${STARTED}, exiting" 1>&2 + exit 1 + else + echo "WARN: Removing stale lock file..." 1>&2 + rm -f "$LOCKFILE" + fi +fi +trap 'rm -f $LOCKFILE' INT TERM EXIT +echo "$$" > "$LOCKFILE" + +for mirror in "$@" ; do + POSTCMD="" + SRC="" + RSYNCOPTS="" + # shellcheck source=/dev/null + . "${CONFDIR}/${mirror}.conf" + if [ "$SRC" = "" ]; then + echo "ERR: No SRC set for mirror ${mirror} ..." 1>&2 + exit 1 + fi + logmsg "Starting ${mirror} sync${NOOP}..." + rsync -aH -4 $EXTRA_OPTS --numeric-ids --delete --delete-delay \ + --delay-updates --no-motd $RSYNCOPTS --log-file="$LOGFILE" \ + --exclude=.~tmp~/ "$SRC" "/srv/mirrors/${mirror}/" + STATUS=$? + if [ $STATUS -ne 0 ]; then + echo "WARN: Encountered errors on ${mirror} sync, see ${LOGFILE} for details" 1>&2 + fi + logmsg "Finished ${mirror} sync with exit status ${STATUS}${NOOP} ..." + if [ "$POSTCMD" != "" ]; then + logmsg "Running post for ${mirror} ..." + $POSTCMD 2>&1 | logstream + logmsg "Finished post for ${mirror} ..." + fi +done diff --git a/roles/mirror/base/tasks/main.yml b/roles/mirror/base/tasks/main.yml index fbeeac4..c28f54b 100644 --- a/roles/mirror/base/tasks/main.yml +++ b/roles/mirror/base/tasks/main.yml @@ -7,7 +7,7 @@ - name: Create mirror group ansible.builtin.group: name: mirror - gid: 1001 + gid: 309 - name: Create mirror user ansible.builtin.user: @@ -17,13 +17,13 @@ group: mirror home: /var/empty shell: /sbin/nologin - uid: 1001 + uid: 309 - name: Create data directory ansible.builtin.file: path: /export/mirrors state: directory - mode: 0755 + mode: "0755" owner: root group: root @@ -44,7 +44,7 @@ ansible.builtin.file: path: /etc/sync-mirrors state: directory - mode: 0755 + mode: "0755" owner: root group: root @@ -52,7 +52,7 @@ ansible.builtin.file: path: "{{ item }}" state: directory - mode: 0755 + mode: "0755" owner: mirror group: mirror with_items: @@ -63,18 +63,25 @@ ansible.builtin.copy: dest: /usr/lib/tmpfiles.d/sync-mirrors.conf content: "d /run/sync-mirrors 0755 mirror mirror\n" - mode: 0644 + mode: "0644" owner: root group: root - name: Copy mirroring script ansible.builtin.copy: dest: /usr/local/bin/sync-mirrors - src: sync-mirrors - mode: 0755 + src: sync-mirrors.sh + mode: "0755" owner: root group: root +- name: Send cron mails to root + ansible.builtin.cron: + name: MAILTO + job: root + env: true + user: mirror + - name: Create mirror cron job ansible.builtin.cron: name: sync-mirrors @@ -103,7 +110,7 @@ ansible.builtin.template: src: mirror.conf.j2 dest: /etc/httpd/conf.local.d/mirror.conf - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" notify: Restart apache diff --git a/roles/mirror/reportmirror/defaults/main.yml b/roles/mirror/reportmirror/defaults/main.yml deleted file mode 100644 index c2ae745..0000000 --- a/roles/mirror/reportmirror/defaults/main.yml +++ /dev/null @@ -1,4 +0,0 @@ ---- - -hostname: "{{ inventory_hostname }}" -mirrors: [] diff --git a/roles/mirror/sync/defaults/main.yml b/roles/mirror/sync/defaults/main.yml index 264336b..58b887d 100644 --- a/roles/mirror/sync/defaults/main.yml +++ b/roles/mirror/sync/defaults/main.yml @@ -1,3 +1,3 @@ --- -rsyncoptions: [] -postcmd: "" +mirror_rsyncoptions: [] +mirror_postcmd: "" diff --git a/roles/mirror/sync/tasks/main.yml b/roles/mirror/sync/tasks/main.yml index ab8c46d..168271d 100644 --- a/roles/mirror/sync/tasks/main.yml +++ b/roles/mirror/sync/tasks/main.yml @@ -1,24 +1,24 @@ --- -- name: Create config for {{ label }} +- name: Create config for {{ mirror_label }} ansible.builtin.template: - dest: "/etc/sync-mirrors/{{ label }}.conf" + dest: "/etc/sync-mirrors/{{ mirror_label }}.conf" src: mirror.conf.j2 - mode: 0644 + mode: "0644" owner: root group: root - name: Create target directory ansible.builtin.file: - path: "/srv/mirrors/{{ label }}" + path: "/srv/mirrors/{{ mirror_label }}" state: directory - mode: 0755 + mode: "0755" owner: mirror group: mirror - name: Link target directory to web ansible.builtin.file: - path: "/srv/web/{{ inventory_hostname }}/{{ label }}" - src: "/srv/mirrors/{{ label }}" + path: "/srv/web/{{ inventory_hostname }}/{{ mirror_label }}" + src: "/srv/mirrors/{{ mirror_label }}" state: link owner: mirror group: mirror diff --git a/roles/mirror/sync/templates/mirror.conf.j2 b/roles/mirror/sync/templates/mirror.conf.j2 index f605577..ab2b6ac 100644 --- a/roles/mirror/sync/templates/mirror.conf.j2 +++ b/roles/mirror/sync/templates/mirror.conf.j2 @@ -1,3 +1,3 @@ -SRC="{{ source }}" -RSYNCOPTS="{{ rsyncoptions | join(' ') }}" -POSTCMD="{{ postcmd }}" +SRC="{{ mirror_source }}" +RSYNCOPTS="{{ mirror_rsyncoptions | join(' ') }}" +POSTCMD="{{ mirror_postcmd }}" diff --git a/roles/mkhomedir/tasks/main.yml b/roles/mkhomedir/tasks/main.yml index eac4cc3..7ec1627 100644 --- a/roles/mkhomedir/tasks/main.yml +++ b/roles/mkhomedir/tasks/main.yml @@ -5,11 +5,15 @@ state: installed - name: Get current state of authselect - ansible.builtin.shell: - cmd: /usr/bin/authselect current --raw ; /bin/true + ansible.builtin.command: + argv: + - /usr/bin/authselect + - current + - "--raw" register: result check_mode: false changed_when: false + failed_when: result.rc not in [0, 2] - name: Enable mkhomedir ansible.builtin.command: diff --git a/roles/mod_auth_gssapi/tasks/main.yml b/roles/mod_auth_gssapi/tasks/main.yml index 621726e..029c374 100644 --- a/roles/mod_auth_gssapi/tasks/main.yml +++ b/roles/mod_auth_gssapi/tasks/main.yml @@ -15,7 +15,7 @@ ansible.builtin.file: path: /etc/systemd/system/httpd.service.d state: directory - mode: 0755 + mode: "0755" owner: root group: "{{ ansible_wheel }}" @@ -23,7 +23,7 @@ ansible.builtin.copy: dest: /etc/systemd/system/httpd.service.d/keytab.conf content: "[Service]\nEnvironment=KRB5_KTNAME=/etc/httpd/httpd.keytab\n" - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" notify: Restart apache diff --git a/roles/mongodb/meta/main.yml b/roles/mongodb/meta/main.yml new file mode 100644 index 0000000..f178512 --- /dev/null +++ b/roles/mongodb/meta/main.yml @@ -0,0 +1,3 @@ +--- +dependencies: + - {role: backup_base} diff --git a/roles/mongodb/tasks/main.yml b/roles/mongodb/tasks/main.yml index 2004130..582b32c 100644 --- a/roles/mongodb/tasks/main.yml +++ b/roles/mongodb/tasks/main.yml @@ -17,10 +17,11 @@ - name: Enable repository ansible.builtin.yum_repository: name: mongodb - baseurl: https://repo.mongodb.org/yum/redhat/8/mongodb-org/5.0/x86_64 + baseurl: >- + https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/6.0/x86_64 description: MongoDB gpgcheck: true - gpgkey: https://www.mongodb.org/static/pgp/server-5.0.asc + gpgkey: https://www.mongodb.org/static/pgp/server-6.0.asc enabled: true - name: Install packages @@ -28,8 +29,9 @@ name: "{{ item }}" state: installed with_items: + - mongodb-database-tools + - mongodb-mongosh - mongodb-org-server - - mongodb-org-shell - name: Set SELinux file contexts on data directory community.general.sefcontext: @@ -40,7 +42,7 @@ ansible.builtin.file: path: /export/mongodb state: directory - mode: 0700 + mode: "0700" owner: mongod group: mongod setype: _default @@ -61,13 +63,14 @@ - "{{ tls_certs }}/{{ inventory_hostname }}.crt" - "{{ tls_private }}/{{ inventory_hostname }}.key" changed_when: false + check_mode: false register: mongodb_cert_key - name: Create combined certificate/private key file ansible.builtin.copy: dest: "{{ tls_private }}/mongodb.pem" content: "{{ mongodb_cert_key.stdout }}" - mode: 0640 + mode: "0640" owner: root group: mongod notify: Restart mongod @@ -76,25 +79,45 @@ ansible.builtin.copy: dest: /etc/logrotate.d/mongod src: mongod.logrotate - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" +- name: Create configuration directory + ansible.builtin.file: + path: /etc/mongod + state: directory + mode: "0750" + owner: root + group: mongod + +- name: Copy keyfile + ansible.builtin.copy: + dest: /etc/mongod/mongod.key + src: "{{ ansible_private }}/files/mongod/mongod.key" + mode: "0400" + owner: mongod + group: mongod + notify: Restart mongod + - name: Configure startup options ansible.builtin.copy: dest: /etc/sysconfig/mongod content: | - OPTIONS="-f /etc/mongod.conf --logRotate reopen" - mode: 0644 - owner: root - group: "{{ ansible_wheel }}" - notify: Restart mongod - -- name: Create configuration - ansible.builtin.template: - dest: /etc/mongod.conf - src: mongod.conf.j2 - mode: 0644 + OPTIONS="-f /etc/mongod.conf \ + --auth \ + --bind_ip_all \ + --dbpath /srv/mongodb \ + --keyFile /etc/mongod/mongod.key \ + --logRotate reopen \ + --nounixsocket + --replSet rs0 \ + --maxConns 16384 \ + --tlsMode requireTLS \ + --tlsCertificateKeyFile {{ tls_private }}/mongodb.pem + --tlsCAFile {{ tls_certs }}/ca.crt + --tlsDisabledProtocols TLS1_0,TLS1_1,TLS1_2" + mode: "0644" owner: root group: "{{ ansible_wheel }}" notify: Restart mongod @@ -105,12 +128,30 @@ state: started enabled: true +- name: Copy backup script + ansible.builtin.template: + dest: /usr/local/sbin/mongodb-backup + src: mongodb-backup.sh.j2 + mode: "0700" + owner: root + group: "{{ ansible_wheel }}" + +- name: Create backup cron job + ansible.builtin.cron: + name: mongodb-backup + job: /usr/local/sbin/mongodb-backup + hour: "0" + minute: "20" + user: root + - name: Create mongo alias cmd for root ansible.builtin.lineinfile: path: /root/.bashrc line: > - alias mongo='mongo + alias mongosh='mongosh --tlsCertificateKeyFile {{ tls_private }}/mongodb.pem --tlsCAFile {{ tls_certs }}/ca.crt + --username root + --password {{ mongodb_root_password }} --tls mongodb://{{ inventory_hostname }}/' - regexp: ^alias mongo=.* + regexp: ^alias mongosh=.* diff --git a/roles/mongodb/templates/mongod.conf.j2 b/roles/mongodb/templates/mongod.conf.j2 deleted file mode 100644 index a05d000..0000000 --- a/roles/mongodb/templates/mongod.conf.j2 +++ /dev/null @@ -1,23 +0,0 @@ - -systemLog: - destination: file - logAppend: true - path: /var/log/mongodb/mongod.log - -storage: - dbPath: /srv/mongodb - journal: - enabled: true - -processManagement: - fork: true - pidFilePath: /var/run/mongodb/mongod.pid - timeZoneInfo: /usr/share/zoneinfo - -net: - port: 27017 - bindIpAll: true - tls: - mode: requireTLS - certificateKeyFile: /etc/pki/tls/private/mongodb.pem - CAFile: {{ tls_certs }}/ca.crt diff --git a/roles/mongodb/templates/mongodb-backup.sh.j2 b/roles/mongodb/templates/mongodb-backup.sh.j2 new file mode 100755 index 0000000..fc415e8 --- /dev/null +++ b/roles/mongodb/templates/mongodb-backup.sh.j2 @@ -0,0 +1,28 @@ +#!/bin/sh + +set -eu + +umask 027 + +DESTDIR="/srv/backup" +DATE="$(date +%Y-%m-%d)" + +cd "$DESTDIR" +find . -xdev -mindepth 3 -maxdepth 3 -type f -mtime +30 \ + -execdir rm -f -- {} \; +find . -xdev -depth -mindepth 1 -maxdepth 2 -type d -empty \ + -execdir rmdir -- {} \; + +mkdir -m 2750 "$DATE" +chgrp backup "$DATE" + +mongodump \ + --sslPEMKeyFile=/etc/pki/tls/private/mongodb.pem \ + --sslCAFile=/etc/pki/tls/certs/ca.crt \ + --ssl \ + --username=backup \ + --password="{{ mongodb_backup_password }}" \ + --gzip \ + --out="${DATE}" \ + --quiet \ + --uri="mongodb://$(hostname -f)/" diff --git a/roles/mosquitto/files/acl.conf b/roles/mosquitto/files/acl.conf new file mode 100644 index 0000000..aa76e34 --- /dev/null +++ b/roles/mosquitto/files/acl.conf @@ -0,0 +1,7 @@ +topic deny # + +user shellyplug-s-* +pattern write shellies/%u/# + +user shellydw2-* +pattern write shellies/%u/# diff --git a/roles/mosquitto/files/mosquitto_tls.ksh b/roles/mosquitto/files/mosquitto_tls.ksh new file mode 100644 index 0000000..9481c35 --- /dev/null +++ b/roles/mosquitto/files/mosquitto_tls.ksh @@ -0,0 +1,10 @@ +#!/bin/ksh + +# shellcheck disable=SC2034 +daemon="/usr/local/sbin/mosquitto -d" +daemon_flags="-c /etc/mosquitto-tls/mosquitto.conf" + +# shellcheck source=/dev/null +. /etc/rc.d/rc.subr + +rc_cmd "$1" diff --git a/roles/mosquitto/handlers/main.yml b/roles/mosquitto/handlers/main.yml index 7e1bb2c..268abc3 100644 --- a/roles/mosquitto/handlers/main.yml +++ b/roles/mosquitto/handlers/main.yml @@ -3,3 +3,8 @@ ansible.builtin.service: name: mosquitto state: restarted + +- name: Restart mosquitto-tls + ansible.builtin.service: + name: mosquitto_tls + state: restarted diff --git a/roles/mosquitto/tasks/main.yml b/roles/mosquitto/tasks/main.yml index 44a1681..d405371 100644 --- a/roles/mosquitto/tasks/main.yml +++ b/roles/mosquitto/tasks/main.yml @@ -9,15 +9,21 @@ name: _mosquitto groups: hostkey append: true - notify: Restart mosquitto + notify: + - Restart mosquitto + - Restart mosquitto-tls -- name: Create include directory for config +- name: Create config directories ansible.builtin.file: - path: /etc/mosquitto/conf.d + path: "{{ item }}" state: directory - mode: 0750 + mode: "0750" owner: root group: _mosquitto + with_items: + - /etc/mosquitto/conf.d + - /etc/mosquitto-tls + - /etc/mosquitto-tls/conf.d - name: Include extra configs ansible.builtin.lineinfile: @@ -26,35 +32,84 @@ regexp: "^#?include_dir( .*)?$" notify: Restart mosquitto -- name: Create custom config +- name: Create custom config for plaintext server ansible.builtin.template: dest: /etc/mosquitto/conf.d/local.conf src: mosquitto.conf.j2 - mode: 0640 + mode: "0640" owner: root group: _mosquitto notify: Restart mosquitto -- name: Copy acl file +- name: Copy acl file for plaintext server ansible.builtin.copy: dest: /etc/mosquitto/acl.conf - src: "{{ ansible_private }}/files/mosquitto/acl.conf" - mode: 0640 - owner: root + src: acl.conf + mode: "0400" + owner: _mosquitto group: _mosquitto notify: Restart mosquitto -- name: Copy passwd file +- name: Copy passwd file for plaintext server ansible.builtin.copy: dest: /etc/mosquitto/passwd src: "{{ ansible_private }}/files/mosquitto/passwd" - mode: 0640 - owner: root + mode: "0400" + owner: _mosquitto group: _mosquitto notify: Restart mosquitto -- name: Enable service +- name: Create default config for tls server + ansible.builtin.command: + argv: + - sed + - "s|^include_dir .*|include_dir /etc/mosquitto-tls/conf.d|" + - /etc/mosquitto/mosquitto.conf + changed_when: false + register: result + +- name: Write default config for tls server + ansible.builtin.copy: + dest: /etc/mosquitto-tls/mosquitto.conf + content: "{{ result.stdout }}\n" + mode: "0640" + owner: root + group: _mosquitto + remote_src: true + notify: Restart mosquitto-tls + +- name: Create custom config for tls server + ansible.builtin.template: + dest: /etc/mosquitto-tls/conf.d/local.conf + src: mosquitto-tls.conf.j2 + mode: "0640" + owner: root + group: _mosquitto + notify: Restart mosquitto-tls + +- name: Create acl file for tls server + ansible.builtin.template: + dest: /etc/mosquitto-tls/acl.conf + src: acl-tls.conf.j2 + mode: "0400" + owner: _mosquitto + group: _mosquitto + notify: Restart mosquitto-tls + +- name: Create mosquitto-tls control script + ansible.builtin.copy: + dest: /etc/rc.d/mosquitto_tls + src: mosquitto_tls.ksh + mode: "0755" + owner: root + group: "{{ ansible_wheel }}" + notify: Restart mosquitto-tls + +- name: Enable services ansible.builtin.service: - name: mosquitto + name: "{{ item }}" enabled: true state: started + with_items: + - mosquitto + - mosquitto_tls diff --git a/roles/mosquitto/templates/acl-tls.conf.j2 b/roles/mosquitto/templates/acl-tls.conf.j2 new file mode 100644 index 0000000..7422313 --- /dev/null +++ b/roles/mosquitto/templates/acl-tls.conf.j2 @@ -0,0 +1,10 @@ +pattern read # + +user {{ inventory_hostname }} +topic readwrite # + +user nms*.home.foo.sh +pattern readwrite # + +user frigate*.home.foo.sh +pattern readwrite frigate/%u/# diff --git a/roles/mosquitto/templates/mosquitto-tls.conf.j2 b/roles/mosquitto/templates/mosquitto-tls.conf.j2 new file mode 100644 index 0000000..7cf1712 --- /dev/null +++ b/roles/mosquitto/templates/mosquitto-tls.conf.j2 @@ -0,0 +1,11 @@ +listener 8883 +protocol mqtt + +certfile {{ tls_certs }}/{{ inventory_hostname }}.crt +keyfile {{ tls_private }}/{{ inventory_hostname }}.key +cafile {{ tls_certs }}/ca.crt +tls_version tlsv1.3 + +acl_file /etc/mosquitto-tls/acl.conf +require_certificate true +use_identity_as_username true diff --git a/roles/mosquitto/templates/mosquitto.conf.j2 b/roles/mosquitto/templates/mosquitto.conf.j2 index f0bc82a..4232fba 100644 --- a/roles/mosquitto/templates/mosquitto.conf.j2 +++ b/roles/mosquitto/templates/mosquitto.conf.j2 @@ -1,17 +1,21 @@ -# authentication +listener 1883 +protocol mqtt + acl_file /etc/mosquitto/acl.conf password_file /etc/mosquitto/passwd allow_anonymous false -# listen to mqtt -listener 1883 -protocol mqtt +connection tls-bridge +address {{ inventory_hostname }}:8883 +bridge_cafile {{ tls_certs }}/ca.crt +bridge_certfile {{ tls_certs }}/{{ inventory_hostname }}.crt +bridge_keyfile {{ tls_private }}/{{ inventory_hostname }}.key -# listen to mqtt over websockets -listener 8883 -protocol websockets - -# tls options -certfile {{ tls_certs }}/{{ inventory_hostname }}.crt -keyfile {{ tls_private }}/{{ inventory_hostname }}.key -cafile {{ tls_certs }}/ca.crt +{% for shelly in shellies %} +{% if shelly['name'] | regex_search("^shellyplug-s-") %} +topic power out 0 shellies/{{ shelly['name'] }}/relay/0/ home/{{ shelly['room'] }}/{{ shelly['device'] }}/ +topic temperature out 0 shellies/{{ shelly['name'] }}/ home/{{ shelly['room'] }}/{{ shelly['device'] }}/ +{% else %} +topic # out 0 shellies/{{ shelly['name'] }}/ home/{{ shelly['room'] }}/{{ shelly['device'] }}/ +{% endif %} +{% endfor %} diff --git a/roles/mysqld_exporter/defaults/main.yml b/roles/mysqld_exporter/defaults/main.yml new file mode 100644 index 0000000..77a7507 --- /dev/null +++ b/roles/mysqld_exporter/defaults/main.yml @@ -0,0 +1,2 @@ +--- +mysqld_exporter_pkg: "mysqld_exporter-{{ mysqld_exporter_version }}.linux-amd64" diff --git a/roles/mysqld_exporter/files/mysqld_exporter.service b/roles/mysqld_exporter/files/mysqld_exporter.service new file mode 100644 index 0000000..c623707 --- /dev/null +++ b/roles/mysqld_exporter/files/mysqld_exporter.service @@ -0,0 +1,14 @@ +[Unit] +Description=Prometheus MySQL Exporter +After=syslog.target +After=network.target + +[Service] +Type=simple +User=mysqld_exporter +Group=mysqld_exporter +ExecStart=/usr/local/bin/mysqld_exporter --config.my-cnf=/etc/mysqld_exporter/my.cnf --web.config.file=/etc/mysqld_exporter/web-config.yml +Restart=always + +[Install] +WantedBy=multi-user.target diff --git a/roles/mysqld_exporter/handlers/main.yml b/roles/mysqld_exporter/handlers/main.yml new file mode 100644 index 0000000..855013c --- /dev/null +++ b/roles/mysqld_exporter/handlers/main.yml @@ -0,0 +1,6 @@ +--- +- name: Restart mysqld_exporter + ansible.builtin.systemd: + name: mysqld_exporter + daemon_reload: true + state: restarted diff --git a/roles/mysqld_exporter/meta/main.yml b/roles/mysqld_exporter/meta/main.yml new file mode 100644 index 0000000..9978a00 --- /dev/null +++ b/roles/mysqld_exporter/meta/main.yml @@ -0,0 +1,3 @@ +--- +dependencies: + - {role: pki} diff --git a/roles/mysqld_exporter/tasks/main.yml b/roles/mysqld_exporter/tasks/main.yml new file mode 100644 index 0000000..d8722d1 --- /dev/null +++ b/roles/mysqld_exporter/tasks/main.yml @@ -0,0 +1,88 @@ +--- +- name: Create group + ansible.builtin.group: + name: mysqld_exporter + system: true + +- name: Create user + ansible.builtin.user: + name: mysqld_exporter + comment: Prometheus MySQL Exporter + group: mysqld_exporter + groups: hostkey + create_home: false + home: /var/empty + shell: /sbin/nologin + system: true + +- name: Download package + ansible.builtin.get_url: + url: >- + {{ + "https://github.com/prometheus/mysqld_exporter/releases/download/v" + + mysqld_exporter_version + "/" + mysqld_exporter_pkg + ".tar.gz" + }} + dest: "/usr/local/src/{{ mysqld_exporter_pkg }}.tar.gz" + mode: "0644" + owner: root + group: "{{ ansible_wheel }}" + +- name: Extract package + ansible.builtin.unarchive: + src: "/usr/local/src/{{ mysqld_exporter_pkg }}.tar.gz" + dest: /usr/local/src + owner: root + group: "{{ ansible_wheel }}" + creates: "/usr/local/src/{{ mysqld_exporter_pkg }}" + remote_src: true + +- name: Copy binary + ansible.builtin.copy: + dest: /usr/local/bin/mysqld_exporter + src: "/usr/local/src/{{ mysqld_exporter_pkg }}/mysqld_exporter" + mode: "0755" + owner: root + group: "{{ ansible_wheel }}" + remote_src: true + notify: Restart mysqld_exporter + +- name: Create config directory + ansible.builtin.file: + path: /etc/mysqld_exporter + state: directory + mode: "0755" + owner: root + group: "{{ ansible_wheel }}" + +- name: Create web-config + ansible.builtin.template: + dest: /etc/mysqld_exporter/web-config.yml + src: web-config.yml.j2 + mode: "0644" + owner: root + group: "{{ ansible_wheel }}" + notify: Restart mysqld_exporter + +- name: Create credentials config + ansible.builtin.template: + dest: /etc/mysqld_exporter/my.cnf + src: my.cnf.j2 + mode: "0640" + owner: root + group: mysqld_exporter + notify: Restart mysqld_exporter + +- name: Create service file + ansible.builtin.copy: + dest: /etc/systemd/system/mysqld_exporter.service + src: mysqld_exporter.service + mode: "0644" + owner: root + group: "{{ ansible_wheel }}" + notify: Restart mysqld_exporter + +- name: Enable service + ansible.builtin.service: + name: mysqld_exporter + state: started + enabled: true diff --git a/roles/mysqld_exporter/templates/my.cnf.j2 b/roles/mysqld_exporter/templates/my.cnf.j2 new file mode 100644 index 0000000..2627e84 --- /dev/null +++ b/roles/mysqld_exporter/templates/my.cnf.j2 @@ -0,0 +1,6 @@ +[client] +user = mysqld_exporter +password = {{ mysqld_exporter_pass }} +ssl-cert = {{ tls_certs }}/{{ inventory_hostname }}.crt +ssl-key = {{ tls_private }}/{{ inventory_hostname }}.key +ssl-ca = {{ tls_certs }}/ca.crt diff --git a/roles/mysqld_exporter/templates/web-config.yml.j2 b/roles/mysqld_exporter/templates/web-config.yml.j2 new file mode 100644 index 0000000..25b4d05 --- /dev/null +++ b/roles/mysqld_exporter/templates/web-config.yml.j2 @@ -0,0 +1,10 @@ +tls_server_config: + key_file: {{ tls_private }}/{{ inventory_hostname }}.key + cert_file: {{ tls_certs }}/{{ inventory_hostname }}.crt + client_ca_file: {{ tls_certs }}/ca.crt + client_auth_type: RequireAndVerifyClientCert + client_allowed_sans: +{% for host in groups['prometheus'] %} + - {{ host }} +{% endfor %} + min_version: TLS13 diff --git a/roles/network/files/keepalived-notify.sh b/roles/network/files/keepalived-notify.sh new file mode 100755 index 0000000..bd709f9 --- /dev/null +++ b/roles/network/files/keepalived-notify.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +set -eu + +umask 022 + +echo "$3" > "/run/keepalived/${2}.state" diff --git a/roles/network/handlers/main.yml b/roles/network/handlers/main.yml index 290312a..945ccb9 100644 --- a/roles/network/handlers/main.yml +++ b/roles/network/handlers/main.yml @@ -12,6 +12,13 @@ - c - reload +- name: Refresh keepalived run directory + ansible.builtin.command: + argv: + - systemd-tmpfiles + - --create + - /etc/tmpfiles.d/keepalived.conf + - name: Restart keepalived ansible.builtin.service: name: keepalived diff --git a/roles/network/tasks/OpenBSD.yml b/roles/network/tasks/OpenBSD.yml index 6c2a5ac..f28a5be 100644 --- a/roles/network/tasks/OpenBSD.yml +++ b/roles/network/tasks/OpenBSD.yml @@ -3,7 +3,7 @@ ansible.builtin.template: src: hostname.if.j2 dest: "/etc/hostname.{{ item.device }}" - mode: 0600 + mode: "0600" owner: root group: "{{ ansible_wheel }}" with_items: "{{ network_interfaces }}" @@ -13,7 +13,7 @@ ansible.builtin.template: src: hostname.carp.j2 dest: "/etc/hostname.carp{{ item.vhid }}" - mode: 0600 + mode: "0600" owner: root group: "{{ ansible_wheel }}" with_items: "{{ network_vip_interfaces }}" @@ -34,7 +34,7 @@ ansible.builtin.copy: content: "{{ network_default_gateway }}\n" dest: /etc/mygate - mode: 0600 + mode: "0600" owner: root group: "{{ ansible_wheel }}" notify: Restart network diff --git a/roles/network/tasks/RedHat.yml b/roles/network/tasks/RedHat.yml index 19b71da..92b38c9 100644 --- a/roles/network/tasks/RedHat.yml +++ b/roles/network/tasks/RedHat.yml @@ -15,11 +15,27 @@ ansible.builtin.template: src: ifcfg-eth.j2 dest: "/etc/sysconfig/network-scripts/ifcfg-{{ item.device }}" - mode: 0644 + mode: "0644" + owner: root + group: "{{ ansible_wheel }}" + # notify: Reload network manager connections + with_items: "{{ network_interfaces }}" + when: + - ansible_distribution != "Fedora" + - ansible_distribution_major_version | int <= 8 + +- name: Create ethernet interface configurations + ansible.builtin.template: + src: nmconnection.j2 + dest: "/etc/NetworkManager/system-connections/{{ item.device }}.nmconnection" + mode: "0600" owner: root group: "{{ ansible_wheel }}" notify: Reload network manager connections with_items: "{{ network_interfaces }}" + when: >- + ansible_distribution == "Fedora" or + ansible_distribution_major_version | int >= 9 - name: Install keepalived ansible.builtin.package: @@ -29,11 +45,55 @@ - network_vip_interfaces is defined - network_vip_interfaces != [] +- name: Create keepalived group + ansible.builtin.group: + name: keepalived + system: true + when: + - network_vip_interfaces is defined + - network_vip_interfaces != [] + +- name: Create keepalived user + ansible.builtin.user: + name: keepalived + comment: Service keepalived + createhome: false + group: keepalived + home: /var/empty + shell: /sbin/nologin + system: true + when: + - network_vip_interfaces is defined + - network_vip_interfaces != [] + +- name: Create run directory + ansible.builtin.copy: + dest: /etc/tmpfiles.d/keepalived.conf + content: "d /run/keepalived 755 keepalived keepalived" + mode: "0644" + owner: root + group: "{{ ansible_wheel }}" + notify: Refresh keepalived run directory + when: + - network_vip_interfaces is defined + - network_vip_interfaces != [] + +- name: Copy keepalived notify script + ansible.builtin.copy: + dest: /usr/local/libexec/keepalived-notify + src: keepalived-notify.sh + mode: "0755" + owner: root + group: "{{ ansible_wheel }}" + when: + - network_vip_interfaces is defined + - network_vip_interfaces != [] + - name: Create keepalived config ansible.builtin.template: dest: /etc/keepalived/keepalived.conf src: keepalived.conf.j2 - mode: 0600 + mode: "0600" owner: root group: "{{ ansible_wheel }}" notify: Restart keepalived diff --git a/roles/network/tasks/main.yml b/roles/network/tasks/main.yml index 6f9d8b6..83d8005 100644 --- a/roles/network/tasks/main.yml +++ b/roles/network/tasks/main.yml @@ -1,12 +1,3 @@ --- - name: Include OS spcific tasks ansible.builtin.include_tasks: "{{ ansible_os_family }}.yml" - -- name: Create resolv.conf - ansible.builtin.template: - src: resolv.conf.j2 - dest: /etc/resolv.conf - mode: 0644 - owner: root - group: "{{ ansible_wheel }}" - when: network_dns_servers is defined diff --git a/roles/network/templates/hostname.if.j2 b/roles/network/templates/hostname.if.j2 index 0db5d8b..862640b 100644 --- a/roles/network/templates/hostname.if.j2 +++ b/roles/network/templates/hostname.if.j2 @@ -1,3 +1,6 @@ +{% if item.rdomain is defined %} +rdomain {{ item.rdomain }} +{% endif %} {% if item.proto is not defined or item.proto == 'dhcp' %} dhcp {% elif item.proto == 'static' %} diff --git a/roles/network/templates/keepalived.conf.j2 b/roles/network/templates/keepalived.conf.j2 index 83c873b..c68642d 100644 --- a/roles/network/templates/keepalived.conf.j2 +++ b/roles/network/templates/keepalived.conf.j2 @@ -1,7 +1,8 @@ ! {{ ansible_managed }} global_defs { - + enable_script_security + script_user keepalived } {% for vip in network_vip_interfaces %} @@ -16,7 +17,8 @@ vrrp_instance VI_{{ vip.vhid }} { auth_pass {{ vip.pass }} } virtual_ipaddress { - {{ vip.ipaddr }} + {{ vip.ipaddr }}/{{ (vip.ipaddr + '/' + vip.netmask) | ansible.utils.ipaddr('prefix') }} } + notify /usr/local/libexec/keepalived-notify } {% endfor %} diff --git a/roles/network/templates/nmconnection.j2 b/roles/network/templates/nmconnection.j2 new file mode 100644 index 0000000..4a27ddb --- /dev/null +++ b/roles/network/templates/nmconnection.j2 @@ -0,0 +1,44 @@ +[connection] +id={{ item.device }} +{% for line in interface_uuid.stdout_lines %} +{% if line.split()[0] == item.device %} +uuid={{ line.split()[1] }} +{% elif line.split()[2] == item.device %} +uuid={{ line.split()[1] }} +{% endif %} +{% endfor %} +type=ethernet +interface-name={{ item.device }} + +[ethernet] + +[ipv4] +{% if item.proto is not defined or item.proto == 'dhcp' %} +method=auto +{% elif item.proto == 'static' %} +method=manual +address1={{ item.ipaddr }}/{{ (item.ipaddr + '/' + item.netmask) | ansible.utils.ipaddr('prefix') }} +{% if item.gateway is defined %} +gateway={{ item.gateway }} +{% endif %} +{% elif item.proto == 'none' %} +method=disabled +{% endif %} +{% if item.nameservers is defined and item.nameservers != [] %} +dns={% for name in item.nameservers %}{{ name }};{% endfor %} + +dns-priority=-10 +{% endif %} + +[ipv6] +addr-gen-mode=eui64 +{% if item.ip6addr is not defined or item.ip6addr == 'none' %} +method=disabled +{% elif item.ip6addr == 'auto' %} +method=auto +{% else %} +method=manual +address1={{ item.ip6addr }} +{% endif %} + +[proxy] diff --git a/roles/network/templates/resolv.conf.j2 b/roles/network/templates/resolv.conf.j2 deleted file mode 100644 index 0e8f587..0000000 --- a/roles/network/templates/resolv.conf.j2 +++ /dev/null @@ -1,6 +0,0 @@ -{% if network_dns_search is defined %} -search {{ network_dns_search|join(' ') }} -{% endif %} -{% for addr in network_dns_servers %} -nameserver {{ addr }} -{% endfor %} diff --git a/roles/nfs_client/meta/main.yml b/roles/nfs_client/meta/main.yml index 14a902c..b5c17d7 100644 --- a/roles/nfs_client/meta/main.yml +++ b/roles/nfs_client/meta/main.yml @@ -1,3 +1,4 @@ --- dependencies: - {role: kerberos} + - {role: tlshd} diff --git a/roles/nfs_client/tasks/main.yml b/roles/nfs_client/tasks/main.yml index 0953d3a..06fe6d6 100644 --- a/roles/nfs_client/tasks/main.yml +++ b/roles/nfs_client/tasks/main.yml @@ -14,7 +14,7 @@ ansible.builtin.copy: dest: /etc/modprobe.d/nfs.conf content: "options nfs nfs4_disable_idmapping=0\n" - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" diff --git a/roles/nfs_server/files/exports b/roles/nfs_server/files/exports new file mode 100644 index 0000000..51916e7 --- /dev/null +++ b/roles/nfs_server/files/exports @@ -0,0 +1,6 @@ +/export/home @nfsclients-rw(rw,root_squash,secure,xprtsec=mtls,sec=sys) \ + @nfsclients-ro(ro,root_squash,secure,xprtsec=mtls,sec=sys) \ + @nfsclients-krb(rw,root_squash,secure,xprtsec=mtls,sec=krb5p) +/export/roles @nfsclients-rw(rw,root_squash,secure,xprtsec=mtls,sec=sys) \ + @nfsclients-ro(ro,root_squash,secure,xprtsec=mtls,sec=sys) \ + @nfsclients-krb(rw,root_squash,secure,xprtsec=mtls,sec=krb5p) diff --git a/roles/nfs_server/files/local.conf b/roles/nfs_server/files/local.conf new file mode 100644 index 0000000..b5085c3 --- /dev/null +++ b/roles/nfs_server/files/local.conf @@ -0,0 +1,7 @@ +[mountd] +debug="auth,general" + +[nfsd] +udp=n +tcp=y +vers3=n diff --git a/roles/nfs_server/tasks/main.yml b/roles/nfs_server/tasks/main.yml index 32b1701..8ac57b1 100644 --- a/roles/nfs_server/tasks/main.yml +++ b/roles/nfs_server/tasks/main.yml @@ -1,27 +1,34 @@ --- -- name: Disable NFS versions 2 and 3 - ansible.builtin.lineinfile: - path: /etc/nfs.conf - line: "{{ item }}=n" - regexp: '^(#\s*)?{{ item }}=.*' - with_items: - - vers2 - - vers3 - notify: Restart nfs-server +- name: Create config directory + ansible.builtin.file: + path: /etc/nfs.conf.d + state: directory + mode: "0755" + owner: root + group: "{{ ansible_wheel }}" -- name: Disable NFS over UDP - ansible.builtin.lineinfile: - path: /etc/nfs.conf - line: "udp=n" - regexp: '^(#\s*)?udp=.*' - insertbefore: vers2=n +- name: Create local config + ansible.builtin.copy: + dest: /etc/nfs.conf.d/local.conf + src: local.conf + mode: "0644" + owner: root + group: "{{ ansible_wheel }}" + +- name: Create exports + ansible.builtin.copy: + dest: /etc/exports + src: exports + mode: "0644" + owner: root + group: "{{ ansible_wheel }}" notify: Restart nfs-server - name: Install home/role autocreate scripts ansible.builtin.copy: dest: "/usr/local/sbin/{{ item }}" src: "{{ item }}.sh" - mode: 0755 + mode: "0755" owner: root group: "{{ ansible_wheel }}" with_items: diff --git a/roles/nftables/tasks/main.yml b/roles/nftables/tasks/main.yml index f60342f..5069a93 100644 --- a/roles/nftables/tasks/main.yml +++ b/roles/nftables/tasks/main.yml @@ -13,9 +13,10 @@ ansible.builtin.template: src: nftables.conf.j2 dest: /etc/sysconfig/nftables.conf - mode: 0600 + mode: "0600" owner: root group: "{{ ansible_wheel }}" + validate: "nft -c -f %s" notify: Reload nftables - name: Enable service diff --git a/roles/nftables/templates/nftables.conf.j2 b/roles/nftables/templates/nftables.conf.j2 index 44f153c..067285c 100644 --- a/roles/nftables/templates/nftables.conf.j2 +++ b/roles/nftables/templates/nftables.conf.j2 @@ -8,6 +8,11 @@ table ip filter { ct state vmap { established : accept, related : accept } ip protocol icmp accept iifname lo accept +{% if firewall_raw is defined %} +{% for rule in firewall_raw %} + {{ rule }} +{% endfor %} +{% endif %} {% for rule in firewall_in %} {% if rule.from is defined %} {% for from in rule.from %} @@ -35,6 +40,11 @@ table ip6 filter { type filter hook input priority 0; policy accept ct state vmap { established : accept, related : accept } ip6 nexthdr icmpv6 accept +{% if firewall_raw6 is defined %} +{% for rule in firewall_raw6 %} + {{ rule }} +{% endfor %} +{% endif %} {% for rule in firewall_in %} {% if rule.from is defined %} {% for from in rule.from %} diff --git a/roles/nginx/server/files/dependency.conf b/roles/nginx/files/dependency.conf similarity index 100% rename from roles/nginx/server/files/dependency.conf rename to roles/nginx/files/dependency.conf diff --git a/roles/nginx/files/nginx-logrotate.sh b/roles/nginx/files/nginx-logrotate.sh new file mode 100755 index 0000000..b7fc0cf --- /dev/null +++ b/roles/nginx/files/nginx-logrotate.sh @@ -0,0 +1,28 @@ +#!/bin/sh + +set -eu + +cd /var/www/logs + +find_rotated() { + find . -mindepth 1 -maxdepth 1 -type f -name "${1}.*" | sort -V -r +} + +for log in *.log ; do + find_rotated "$log" | while read -r name; do + ext="${name##*.}" + next="${name%.*}.$((ext+1))" + mv "$name" "$next" + done + mv "$log" "${log}.1" + touch "$log" + + find_rotated "$log" | while read -r name; do + num="$(echo "$name" | awk -F. '{ print $NF }')" + if [ "$num" -gt 7 ]; then + rm -f "${log}.${num}" + fi + done +done + +kill -USR1 "$(cat /var/run/nginx.pid)" diff --git a/roles/nginx/server/handlers/main.yml b/roles/nginx/handlers/main.yml similarity index 100% rename from roles/nginx/server/handlers/main.yml rename to roles/nginx/handlers/main.yml diff --git a/roles/nginx/server/meta/main.yml b/roles/nginx/meta/main.yml similarity index 100% rename from roles/nginx/server/meta/main.yml rename to roles/nginx/meta/main.yml diff --git a/roles/nginx/site/tasks/main.yml b/roles/nginx/site/tasks/main.yml deleted file mode 100644 index fbb2793..0000000 --- a/roles/nginx/site/tasks/main.yml +++ /dev/null @@ -1,47 +0,0 @@ ---- -- name: "Create site data directory for {{ site }}" - ansible.builtin.file: - path: "/srv/web/{{ site }}" - state: directory - mode: 0755 - owner: root - group: "{{ ansible_wheel }}" - when: redirect is not defined and proxy is not defined - -- name: "Create site config for {{ site }}" - ansible.builtin.template: - dest: /etc/nginx/conf.d/{{ site }}.conf - src: site.conf.j2 - mode: 0644 - owner: root - group: "{{ ansible_wheel }}" - notify: Restart nginx - -- name: "Copy site private key for {{ site }}" - ansible.builtin.copy: - dest: "{{ tls_private }}/{{ site }}.key" - src: "{{ item }}" - mode: 0600 - owner: root - group: "{{ ansible_wheel }}" - with_first_found: - - "/srv/letsencrypt/live/{{ site }}/privkey.pem" - - "/srv/ca/private/{{ site }}.key" - - "/srv/ca/private/{{ inventory_hostname }}.key" - tags: certificates - notify: Restart nginx - -- name: "Copy site certificate for {{ site }}" - ansible.builtin.copy: - src: "{{ item }}" - dest: "{{ tls_certs }}/{{ site }}-fullchain.crt" - mode: 0644 - owner: root - group: "{{ ansible_wheel }}" - validate: /usr/bin/openssl x509 -in %s -noout - with_first_found: - - "/srv/letsencrypt/live/{{ site }}/fullchain.pem" - - "/srv/ca/certs/hosts/{{ site }}.crt" - - "/srv/ca/certs/hosts/{{ inventory_hostname }}.crt" - tags: certificates - notify: Restart nginx diff --git a/roles/nginx/site/templates/site.conf.j2 b/roles/nginx/site/templates/site.conf.j2 deleted file mode 100644 index a277ec5..0000000 --- a/roles/nginx/site/templates/site.conf.j2 +++ /dev/null @@ -1,66 +0,0 @@ -{% if proxy is defined and proxy is not string %} -upstream upstream-{{ site }} { -{% for item in proxy %} -{% set item = item | regex_replace("^(https://)?([^/]*).*$", "\\2") %} -{% if item | regex_search(".*:[0-9]+$") %} - server {{ item }}; -{% else %} - server {{ item }}:443; -{% endif %} -{% endfor %} -} -{% endif %} -server { - listen 443 ssl http2; - listen [::]:443 ssl http2; - server_name {{ site }}; - - access_log {{ nginx_logdir }}/{{ site }}.access.log combined; - error_log {{ nginx_logdir }}/{{ site }}.error.log warn; - - add_header Strict-Transport-Security "max-age=63072000" always; - -{% if ssl_config is defined %} -{% if ssl_config == "old" %} - ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; - ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA; - ssl_prefer_server_ciphers on; -{% endif %} -{% endif %} - ssl_certificate {{ tls_certs }}/{{ site }}-fullchain.crt; - ssl_certificate_key {{ tls_private }}/{{ site }}.key; - -{% include "./{}.conf.j2".format(site) ignore missing %} -{% if redirect is defined %} - return 301 {{ redirect }}; -{% elif proxy is defined %} - location / { -{% if proxy is not string %} -{% set path = proxy[0] | regex_replace("^(https://)?([^/]*)(.*)$", "\\3") %} - # https://trac.nginx.org/nginx/ticket/1307 - proxy_ssl_verify off; - proxy_pass https://upstream-{{ site }}{{ path }}; -{% else %} - proxy_pass {{ proxy }}; -{% endif %} - } -{% else %} - root /srv/web/{{ site }}; -{% endif %} -} - -server { - listen 80; - listen [::]:80; - server_name {{ site }}; - location /.well-known/acme-challenge/ { - proxy_pass https://certbot.home.foo.sh/.well-known/acme-challenge/; - } - location / { -{% if redirect is defined %} - return 301 {{ redirect }}; -{% else %} - return 301 https://$host$request_uri; -{% endif %} - } -} diff --git a/roles/nginx/server/tasks/main.yml b/roles/nginx/tasks/main.yml similarity index 69% rename from roles/nginx/server/tasks/main.yml rename to roles/nginx/tasks/main.yml index 33fc042..a397adf 100644 --- a/roles/nginx/server/tasks/main.yml +++ b/roles/nginx/tasks/main.yml @@ -2,18 +2,19 @@ - name: Include OS-specific variables ansible.builtin.include_vars: "{{ ansible_os_family }}.yml" -- name: Enable nginx:120 module +- name: Enable nginx:124 module ansible.builtin.command: argv: - dnf - module - -y - enable - - nginx:1.20 + - nginx:1.24 creates: /etc/dnf/modules.d/nginx.module + notify: Restart nginx when: - ansible_os_family == "RedHat" - - ansible_distribution_major_version | int == 8 + - ansible_distribution_major_version | int >= 9 - ansible_distribution != "Fedora" - name: Install packages @@ -31,7 +32,7 @@ ansible.builtin.file: state: directory path: "{{ item }}" - mode: 0755 + mode: "0755" owner: root group: "{{ ansible_wheel }}" seuser: _default @@ -45,7 +46,7 @@ ansible.builtin.template: src: nginx.conf.j2 dest: /etc/nginx/nginx.conf - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" notify: Restart nginx @@ -55,7 +56,7 @@ ansible.builtin.file: dest: /etc/systemd/system/nginx.service.d state: directory - mode: 0755 + mode: "0755" owner: root group: "{{ ansible_wheel }}" when: ansible_os_family == "RedHat" @@ -64,11 +65,35 @@ ansible.builtin.copy: dest: /etc/systemd/system/nginx.service.d/dependency.conf src: dependency.conf - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" when: ansible_os_family == "RedHat" +- name: Disable web logs from newsyslog + ansible.builtin.replace: + path: /etc/newsyslog.conf + regexp: "^/var/www/logs/" + replace: "#/var/www/logs/" + when: ansible_system == "OpenBSD" + +- name: Install logrotate script + ansible.builtin.copy: + dest: /usr/local/bin/nginx-logrotate + src: nginx-logrotate.sh + mode: "0755" + owner: root + group: "{{ ansible_wheel }}" + when: ansible_system == "OpenBSD" + +- name: Add logrotate cron job + ansible.builtin.cron: + name: nginx-logrotate + hour: "0" + minute: "0" + job: /usr/local/bin/nginx-logrotate + when: ansible_system == "OpenBSD" + - name: Enable nginx service ansible.builtin.service: name: nginx diff --git a/roles/nginx/server/templates/nginx-logrotate.sh b/roles/nginx/templates/nginx-logrotate.sh similarity index 100% rename from roles/nginx/server/templates/nginx-logrotate.sh rename to roles/nginx/templates/nginx-logrotate.sh diff --git a/roles/nginx/server/templates/nginx.conf.j2 b/roles/nginx/templates/nginx.conf.j2 similarity index 76% rename from roles/nginx/server/templates/nginx.conf.j2 rename to roles/nginx/templates/nginx.conf.j2 index 1bc0e2b..b6733d2 100644 --- a/roles/nginx/server/templates/nginx.conf.j2 +++ b/roles/nginx/templates/nginx.conf.j2 @@ -8,7 +8,10 @@ events { } http { - access_log {{ nginx_logdir }}/access.log combined; + log_format custom '$remote_addr - $remote_user [$time_local] ' + '"$request" $status $body_bytes_sent ' + '"$http_referer" "$http_user_agent" ($request_time)'; + access_log {{ nginx_logdir }}/access.log custom; proxy_ssl_certificate {{ tls_certs }}/{{ inventory_hostname }}.crt; proxy_ssl_certificate_key {{ tls_private }}/{{ inventory_hostname }}.key; @@ -23,16 +26,19 @@ http { } proxy_set_header Connection $connection_upgrade; proxy_set_header Upgrade $http_upgrade; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Host $host; + proxy_set_header X-Forwarded-Proto $scheme; proxy_http_version 1.1; -{% if plaintext is defined %} +{% if nginx_plaintext is defined %} server { listen 80; listen [::]:80; server_name {{ inventory_hostname }}; location /.well-known/acme-challenge/ { - proxy_pass https://certbot.home.foo.sh/.well-known/acme-challenge/; + proxy_pass http://certbot.home.foo.sh/.well-known/acme-challenge/; } location / { return 301 https://$host$request_uri; @@ -60,6 +66,10 @@ http { root /srv/web/{{ inventory_hostname }}; + location = /stub_status { + stub_status; + } + include /etc/nginx/conf.d/{{ inventory_hostname }}/*.conf; } diff --git a/roles/nginx/server/vars/OpenBSD.yml b/roles/nginx/vars/OpenBSD.yml similarity index 100% rename from roles/nginx/server/vars/OpenBSD.yml rename to roles/nginx/vars/OpenBSD.yml diff --git a/roles/nginx/server/vars/RedHat.yml b/roles/nginx/vars/RedHat.yml similarity index 100% rename from roles/nginx/server/vars/RedHat.yml rename to roles/nginx/vars/RedHat.yml diff --git a/roles/nginx_exporter/defaults/main.yml b/roles/nginx_exporter/defaults/main.yml new file mode 100644 index 0000000..6f214a3 --- /dev/null +++ b/roles/nginx_exporter/defaults/main.yml @@ -0,0 +1,3 @@ +--- +nginx_exporter_pkg: >- + nginx-prometheus-exporter_{{ nginx_exporter_version }}_linux_amd64 diff --git a/roles/nginx_exporter/handlers/main.yml b/roles/nginx_exporter/handlers/main.yml new file mode 100644 index 0000000..690f1c7 --- /dev/null +++ b/roles/nginx_exporter/handlers/main.yml @@ -0,0 +1,6 @@ +--- +- name: Restart nginx_exporter + ansible.builtin.systemd: + name: nginx_exporter + daemon_reload: true + state: restarted diff --git a/roles/nginx_exporter/tasks/main.yml b/roles/nginx_exporter/tasks/main.yml new file mode 100644 index 0000000..8d445ed --- /dev/null +++ b/roles/nginx_exporter/tasks/main.yml @@ -0,0 +1,88 @@ +--- +- name: Create group + ansible.builtin.group: + name: nginx_exporter + system: true + +- name: Create user + ansible.builtin.user: + name: nginx_exporter + comment: Prometheus NGINX Exporter + group: nginx_exporter + groups: hostkey + create_home: false + home: /var/empty + shell: /sbin/nologin + system: true + +- name: Download package + ansible.builtin.get_url: + url: >- + {{ + "https://github.com/nginxinc/nginx-prometheus-exporter/releases/" + + "download/v" + nginx_exporter_version + "/" + nginx_exporter_pkg + + ".tar.gz" + }} + dest: "/usr/local/src/{{ nginx_exporter_pkg }}.tar.gz" + mode: "0644" + owner: root + group: "{{ ansible_wheel }}" + +- name: Create directory for extracing package + ansible.builtin.file: + path: "/usr/local/src/{{ nginx_exporter_pkg }}" + state: directory + mode: "0755" + owner: root + group: "{{ ansible_wheel }}" + +- name: Extract nginx_exporter + ansible.builtin.unarchive: + src: "/usr/local/src/{{ nginx_exporter_pkg }}.tar.gz" + dest: "/usr/local/src/{{ nginx_exporter_pkg }}" + owner: root + group: "{{ ansible_wheel }}" + creates: "/usr/local/src/{{ nginx_exporter_pkg }}/nginx-prometheus-exporter" + remote_src: true + +- name: Copy binary + ansible.builtin.copy: + dest: "/usr/local/bin/nginx_exporter" + src: "/usr/local/src/{{ nginx_exporter_pkg }}/nginx-prometheus-exporter" + mode: "0755" + owner: root + group: "{{ ansible_wheel }}" + remote_src: true + notify: Restart nginx_exporter + +- name: Create config directory + ansible.builtin.file: + path: /etc/nginx_exporter + state: directory + mode: "0755" + owner: root + group: "{{ ansible_wheel }}" + +- name: Create web-config + ansible.builtin.template: + dest: /etc/nginx_exporter/web-config.yml + src: web-config.yml.j2 + mode: "0644" + owner: root + group: "{{ ansible_wheel }}" + notify: Restart nginx_exporter + +- name: Create service file + ansible.builtin.template: + dest: /etc/systemd/system/nginx_exporter.service + src: nginx_exporter.service.j2 + mode: "0644" + owner: root + group: "{{ ansible_wheel }}" + notify: Restart nginx_exporter + +- name: Enable service + ansible.builtin.service: + name: nginx_exporter + state: started + enabled: true diff --git a/roles/nginx_exporter/templates/nginx_exporter.service.j2 b/roles/nginx_exporter/templates/nginx_exporter.service.j2 new file mode 100644 index 0000000..bf1eb12 --- /dev/null +++ b/roles/nginx_exporter/templates/nginx_exporter.service.j2 @@ -0,0 +1,21 @@ +[Unit] +Description=Prometheus NGINX Exporter +After=syslog.target +After=network.target + +[Service] +Type=simple +User=nginx_exporter +Group=nginx_exporter +ExecStart=/usr/local/bin/nginx_exporter \ + --web.config.file=/etc/nginx_exporter/web-config.yml \ +{% for host in groups['proxy'] %} + --nginx.scrape-uri=https://{{ host }}/stub_status \ +{% endfor %} + --nginx.ssl-ca-cert={{ tls_certs }}/ca.crt \ + --nginx.ssl-client-cert={{ tls_certs }}/{{ inventory_hostname }}.crt \ + --nginx.ssl-client-key={{ tls_private }}/{{ inventory_hostname }}.key +Restart=always + +[Install] +WantedBy=multi-user.target diff --git a/roles/nginx_exporter/templates/web-config.yml.j2 b/roles/nginx_exporter/templates/web-config.yml.j2 new file mode 100644 index 0000000..03e5466 --- /dev/null +++ b/roles/nginx_exporter/templates/web-config.yml.j2 @@ -0,0 +1,11 @@ +--- +tls_server_config: + key_file: {{ tls_private }}/{{ inventory_hostname }}.key + cert_file: {{ tls_certs }}/{{ inventory_hostname }}.crt + client_ca_file: {{ tls_certs }}/ca.crt + client_auth_type: RequireAndVerifyClientCert + client_allowed_sans: +{% for host in groups['prometheus'] %} + - {{ host }} +{% endfor %} + min_version: TLS13 diff --git a/roles/nginx_logsync/tasks/main.yml b/roles/nginx_logsync/tasks/main.yml new file mode 100644 index 0000000..0d7c9ff --- /dev/null +++ b/roles/nginx_logsync/tasks/main.yml @@ -0,0 +1,34 @@ +--- +- name: Create group + ansible.builtin.group: + name: logsync + system: true + +- name: Create user + ansible.builtin.user: + name: logsync + comment: Service logsync + create_home: false + group: logsync + home: /var/empty + shell: /sbin/nologin + +- name: Create authorized_keys + ansible.builtin.copy: + dest: /etc/ssh/authorized_keys.logsync + src: ../files/ssh/logsync.pub + mode: "0640" + owner: root + group: logsync + +- name: Configure sshd chroot + ansible.builtin.blockinfile: + path: /etc/ssh/sshd_config + block: | + Match User logsync + ChrootDirectory /var/www/logs + ForceCommand internal-sftp + AuthorizedKeysFile /etc/ssh/authorized_keys.logsync + marker: "# {mark} ANSIBLE MANAGED BLOCK (user logsync)" + validate: "sshd -t -f %s" + notify: Restart sshd diff --git a/roles/nginx_site/defaults/main.yml b/roles/nginx_site/defaults/main.yml new file mode 100644 index 0000000..2296dbc --- /dev/null +++ b/roles/nginx_site/defaults/main.yml @@ -0,0 +1,2 @@ +--- +nginx_site_plaintext: true diff --git a/roles/nginx_site/tasks/main.yml b/roles/nginx_site/tasks/main.yml new file mode 100644 index 0000000..0afcf5e --- /dev/null +++ b/roles/nginx_site/tasks/main.yml @@ -0,0 +1,47 @@ +--- +- name: "Create site data directory for {{ nginx_site_name }}" + ansible.builtin.file: + path: "/srv/web/{{ nginx_site_name }}" + state: directory + mode: "0755" + owner: root + group: "{{ ansible_wheel }}" + when: nginx_site_redirect is not defined and nginx_site_proxy is not defined + +- name: "Create site config for {{ nginx_site_name }}" + ansible.builtin.template: + dest: /etc/nginx/conf.d/{{ nginx_site_name }}.conf + src: site.conf.j2 + mode: "0644" + owner: root + group: "{{ ansible_wheel }}" + notify: Restart nginx + +- name: "Copy site private key for {{ nginx_site_name }}" + ansible.builtin.copy: + dest: "{{ tls_private }}/{{ nginx_site_name }}.key" + src: "{{ item }}" + mode: "0600" + owner: root + group: "{{ ansible_wheel }}" + with_first_found: + - "/srv/letsencrypt/live/{{ nginx_site_name }}/privkey.pem" + - "/srv/ca/private/{{ nginx_site_name }}.key" + - "/srv/ca/private/{{ inventory_hostname }}.key" + tags: certificates + notify: Restart nginx + +- name: "Copy site certificate for {{ nginx_site_name }}" + ansible.builtin.copy: + src: "{{ item }}" + dest: "{{ tls_certs }}/{{ nginx_site_name }}-fullchain.crt" + mode: "0644" + owner: root + group: "{{ ansible_wheel }}" + validate: /usr/bin/openssl x509 -in %s -noout + with_first_found: + - "/srv/letsencrypt/live/{{ nginx_site_name }}/fullchain.pem" + - "/srv/ca/certs/hosts/{{ nginx_site_name }}.crt" + - "/srv/ca/certs/hosts/{{ inventory_hostname }}.crt" + tags: certificates + notify: Restart nginx diff --git a/roles/nginx_site/templates/audiobooks.foo.sh.conf.j2 b/roles/nginx_site/templates/audiobooks.foo.sh.conf.j2 new file mode 100644 index 0000000..e838c5f --- /dev/null +++ b/roles/nginx_site/templates/audiobooks.foo.sh.conf.j2 @@ -0,0 +1,3 @@ + # this should be changed to only affect uploads + client_max_body_size 10g; + diff --git a/roles/nginx_site/templates/collab.foo.sh.conf.j2 b/roles/nginx_site/templates/collab.foo.sh.conf.j2 new file mode 100644 index 0000000..93e1c8b --- /dev/null +++ b/roles/nginx_site/templates/collab.foo.sh.conf.j2 @@ -0,0 +1,6 @@ + client_max_body_size 50m; + + add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'"; + add_header Referrer-Policy "no-referrer"; + add_header X-Content-Type-Options "nosniff"; + add_header X-XSS-Protection "1; mode=block"; diff --git a/roles/nginx_site/templates/git.foo.sh.conf.j2 b/roles/nginx_site/templates/git.foo.sh.conf.j2 new file mode 100644 index 0000000..4bfc067 --- /dev/null +++ b/roles/nginx_site/templates/git.foo.sh.conf.j2 @@ -0,0 +1,2 @@ + # disable any limits to avoid HTTP 413 for large pushes + client_max_body_size 100m; diff --git a/roles/nginx/site/templates/gw.home.foo.sh.conf.j2 b/roles/nginx_site/templates/gw.home.foo.sh.conf.j2 similarity index 100% rename from roles/nginx/site/templates/gw.home.foo.sh.conf.j2 rename to roles/nginx_site/templates/gw.home.foo.sh.conf.j2 diff --git a/roles/nginx_site/templates/movies.foo.sh.conf.j2 b/roles/nginx_site/templates/movies.foo.sh.conf.j2 new file mode 100644 index 0000000..760e07b --- /dev/null +++ b/roles/nginx_site/templates/movies.foo.sh.conf.j2 @@ -0,0 +1,5 @@ + add_header Content-Security-Policy "default-src 'self'; font-src 'self' https://fonts.gstatic.com; img-src 'self' data:; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com"; + add_header Referrer-Policy "no-referrer"; + add_header X-Content-Type-Options "nosniff"; + add_header X-XSS-Protection "1; mode=block"; + diff --git a/roles/nginx/site/templates/registry.foo.sh.conf.j2 b/roles/nginx_site/templates/registry.foo.sh.conf.j2 similarity index 100% rename from roles/nginx/site/templates/registry.foo.sh.conf.j2 rename to roles/nginx_site/templates/registry.foo.sh.conf.j2 diff --git a/roles/nginx_site/templates/site.conf.j2 b/roles/nginx_site/templates/site.conf.j2 new file mode 100644 index 0000000..ca54573 --- /dev/null +++ b/roles/nginx_site/templates/site.conf.j2 @@ -0,0 +1,68 @@ +{% if nginx_site_proxy is defined and nginx_site_proxy is not string %} +upstream {{ nginx_site_name }} { +{% if nginx_site_load_balance_method is defined %} + {{ nginx_site_load_balance_method }}; +{% endif %} +{% for item in nginx_site_proxy %} +{% set item = item | regex_replace("^(https://)?([^/]*).*$", "\\2") %} +{% if item | regex_search(".*:[0-9]+$") %} + server {{ item }}; +{% else %} + server {{ item }}:443; +{% endif %} +{% endfor %} +} +{% endif %} +server { + listen 443 ssl http2; + listen [::]:443 ssl http2; + server_name {{ nginx_site_name }}; + + access_log {{ nginx_logdir }}/{{ nginx_site_name }}.access.log custom; + error_log {{ nginx_logdir }}/{{ nginx_site_name }}.error.log warn; + + add_header Strict-Transport-Security "max-age=63072000" always; + + ssl_certificate {{ tls_certs }}/{{ nginx_site_name }}-fullchain.crt; + ssl_certificate_key {{ tls_private }}/{{ nginx_site_name }}.key; + +{% include "./{}.conf.j2".format(nginx_site_name) ignore missing %} +{% if nginx_site_redirect is defined %} + return 301 {{ nginx_site_redirect }}; +{% elif nginx_site_proxy is defined %} + location / { +{% if nginx_site_proxy is not string %} +{% set path = nginx_site_proxy[0] | regex_replace("^(https://)?([^/]*)(.*)$", "\\3") %} + # https://trac.nginx.org/nginx/ticket/1307 + proxy_ssl_verify off; + proxy_pass https://{{ nginx_site_name }}{{ path }}; +{% else %} + proxy_pass {{ nginx_site_proxy }}; +{% endif %} + } +{% else %} + root /srv/web/{{ nginx_site_name }}; +{% endif %} +} +{% if nginx_site_plaintext %} + +server { + listen 80; + listen [::]:80; + server_name {{ nginx_site_name }}; +{% if nginx_site_name == 'certbot.home.foo.sh' and 'proxy' not in groups %} + root /srv/web/{{ nginx_site_name }}; +{% else %} + location /.well-known/acme-challenge/ { + proxy_pass https://certbot.home.foo.sh/.well-known/acme-challenge/; + } + location / { +{% if nginx_site_redirect is defined %} + return 301 {{ nginx_site_redirect }}; +{% else %} + return 301 https://$host$request_uri; +{% endif %} + } +{% endif %} +} +{% endif %} diff --git a/roles/nginx/site/templates/www.foo.sh.conf.j2 b/roles/nginx_site/templates/www.foo.sh.conf.j2 similarity index 100% rename from roles/nginx/site/templates/www.foo.sh.conf.j2 rename to roles/nginx_site/templates/www.foo.sh.conf.j2 diff --git a/roles/node_exporter/files/md_info.sh b/roles/node_exporter/files/md_info.sh new file mode 100755 index 0000000..bf72d1b --- /dev/null +++ b/roles/node_exporter/files/md_info.sh @@ -0,0 +1,59 @@ +#!/usr/bin/env bash + +set -eu + +for MD_DEVICE in /dev/md/*; do + if [ -b "$MD_DEVICE" ]; then + # Subshell to avoid eval'd variables from leaking between iterations + ( + # Resolve symlink to discover device, e.g. /dev/md127 + MD_DEVICE_NUM=$(readlink -f "${MD_DEVICE}") + + # Remove /dev/ prefix + MD_DEVICE_NUM=${MD_DEVICE_NUM#/dev/} + MD_DEVICE=${MD_DEVICE#/dev/md/} + + # Query sysfs for info about md device + SYSFS_BASE="/sys/devices/virtual/block/${MD_DEVICE_NUM}/md" + MD_LAYOUT=$(cat "${SYSFS_BASE}/layout") + MD_LEVEL=$(cat "${SYSFS_BASE}/level") + MD_METADATA_VERSION=$(cat "${SYSFS_BASE}/metadata_version") + MD_NUM_RAID_DISKS=$(cat "${SYSFS_BASE}/raid_disks") + + # Remove 'raid' prefix from RAID level + MD_LEVEL=${MD_LEVEL#raid} + + # Output disk metrics + for RAID_DISK in "${SYSFS_BASE}"/rd[0-9]*; do + DISK=$(readlink -f "${RAID_DISK}/block") + DISK_DEVICE=$(basename "${DISK}") + RAID_DISK_DEVICE=$(basename "${RAID_DISK}") + RAID_DISK_INDEX=${RAID_DISK_DEVICE#rd} + RAID_DISK_STATE=$(cat "${RAID_DISK}/state") + + DISK_SET="" + # Determine disk set using logic from mdadm: https://github.com/neilbrown/mdadm/commit/2c096ebe4b + if [[ ${RAID_DISK_STATE} == "in_sync" && ${MD_LEVEL} == 10 && $((MD_LAYOUT & ~0x1ffff)) ]]; then + NEAR_COPIES=$((MD_LAYOUT & 0xff)) + FAR_COPIES=$(((MD_LAYOUT >> 8) & 0xff)) + COPIES=$((NEAR_COPIES * FAR_COPIES)) + + if [[ $((MD_NUM_RAID_DISKS % COPIES == 0)) && $((COPIES <= 26)) ]]; then + DISK_SET=$((RAID_DISK_INDEX % COPIES)) + fi + fi + + echo -n "node_md_disk_info{disk_device=\"${DISK_DEVICE}\", md_device=\"${MD_DEVICE_NUM}\"" + if [[ -n ${DISK_SET} ]]; then + SET_LETTERS=({A..Z}) + echo -n ", md_set=\"${SET_LETTERS[${DISK_SET}]}\"" + fi + echo "} 1" + done + + # Output RAID array metrics + # NOTE: Metadata version is a label rather than a separate metric because the version can be a string + echo "node_md_info{md_device=\"${MD_DEVICE_NUM}\", md_name=\"${MD_DEVICE}\", raid_level=\"${MD_LEVEL}\", md_metadata_version=\"${MD_METADATA_VERSION}\"} 1" + ) + fi +done diff --git a/roles/node_exporter/files/node-exporter-run-textfile-collector.sh b/roles/node_exporter/files/node-exporter-run-textfile-collector.sh new file mode 100755 index 0000000..97dd14c --- /dev/null +++ b/roles/node_exporter/files/node-exporter-run-textfile-collector.sh @@ -0,0 +1,40 @@ +#!/bin/sh + +set -eu + +umask 022 + +PATH="/bin:/usr/bin:/usr/local/bin:/sbin:/usr/sbin:/usr/local/sbin" + +if [ "${1:-}" = "-v" ]; then + shift + VERBOSE=true +else + VERBOSE=false +fi + +if [ -n "${1:-}" ]; then + echo "Usage: $(basename "$0") [-v]" 1>&2 + exit 1 +fi + +if [ "$(uname -s)" = "OpenBSD" ]; then + OUTDIR="/var/db/node-exporter" +else + OUTDIR="/var/lib/prometheus/node-exporter" +fi +"$VERBOSE" && echo "Using output directory '${OUTDIR}'" + +for script in /usr/local/libexec/node-exporter/*; do + [ -x "$script" ] || continue + "$VERBOSE" && echo "Processing script '${script}'" + target="${OUTDIR}/$(basename "$script")" + tmpfile="$(mktemp -p "$OUTDIR")" + if "$script" > "$tmpfile" ; then + "$VERBOSE" && echo " Success, updating stats" + mv "$tmpfile" "$target" + else + "$VERBOSE" && echo " Failure, skipping stats update" + rm -f "$tmpfile" + fi +done diff --git a/roles/node_exporter/files/smartmon.sh b/roles/node_exporter/files/smartmon.sh new file mode 100755 index 0000000..4cefec5 --- /dev/null +++ b/roles/node_exporter/files/smartmon.sh @@ -0,0 +1,204 @@ +#!/usr/bin/env bash +# +# Script informed by the collectd monitoring script for smartmontools (using smartctl) +# by Samuel B. (c) 2012 +# source at: http://devel.dob.sk/collectd-scripts/ + +# TODO: This probably needs to be a little more complex. The raw numbers can have more +# data in them than you'd think. +# http://arstechnica.com/civis/viewtopic.php?p=22062211 + +# Formatting done via shfmt -i 2 +# https://github.com/mvdan/sh + +# Ensure predictable numeric / date formats, etc. +export LC_ALL=C + +parse_smartctl_attributes_awk="$( + cat <<'SMARTCTLAWK' +$1 ~ /^ *[0-9]+$/ && $2 ~ /^[a-zA-Z0-9_-]+$/ { + gsub(/-/, "_"); + printf "%s_value{%s,smart_id=\"%s\"} %d\n", $2, labels, $1, $4 + printf "%s_worst{%s,smart_id=\"%s\"} %d\n", $2, labels, $1, $5 + printf "%s_threshold{%s,smart_id=\"%s\"} %d\n", $2, labels, $1, $6 + printf "%s_raw_value{%s,smart_id=\"%s\"} %e\n", $2, labels, $1, $10 +} +SMARTCTLAWK +)" + +smartmon_attrs="$( + cat <<'SMARTMONATTRS' +airflow_temperature_cel +command_timeout +current_pending_sector +end_to_end_error +erase_fail_count +g_sense_error_rate +hardware_ecc_recovered +host_reads_32mib +host_reads_mib +host_writes_32mib +host_writes_mib +load_cycle_count +media_wearout_indicator +nand_writes_1gib +offline_uncorrectable +power_cycle_count +power_on_hours +program_fail_cnt_total +program_fail_count +raw_read_error_rate +reallocated_event_count +reallocated_sector_ct +reported_uncorrect +runtime_bad_block +sata_downshift_count +seek_error_rate +spin_retry_count +spin_up_time +start_stop_count +temperature_case +temperature_celsius +temperature_internal +total_lbas_read +total_lbas_written +udma_crc_error_count +unsafe_shutdown_count +unused_rsvd_blk_cnt_tot +wear_leveling_count +workld_host_reads_perc +workld_media_wear_indic +workload_minutes +SMARTMONATTRS +)" +smartmon_attrs="$(echo "${smartmon_attrs}" | xargs | tr ' ' '|')" + +parse_smartctl_attributes() { + local disk="$1" + local disk_type="$2" + local labels="disk=\"${disk}\",type=\"${disk_type}\"" + sed 's/^ \+//g' | + awk -v labels="${labels}" "${parse_smartctl_attributes_awk}" 2>/dev/null | + tr '[:upper:]' '[:lower:]' | + grep -E "(${smartmon_attrs})" +} + +parse_smartctl_scsi_attributes() { + local disk="$1" + local disk_type="$2" + local labels="disk=\"${disk}\",type=\"${disk_type}\"" + while read -r line; do + attr_type="$(echo "${line}" | tr '=' ':' | cut -f1 -d: | sed 's/^ \+//g' | tr ' ' '_')" + attr_value="$(echo "${line}" | tr '=' ':' | cut -f2 -d: | sed 's/^ \+//g')" + case "${attr_type}" in + number_of_hours_powered_up_) power_on="$(echo "${attr_value}" | awk '{ printf "%e\n", $1 }')" ;; + Current_Drive_Temperature) temp_cel="$(echo "${attr_value}" | cut -f1 -d' ' | awk '{ printf "%e\n", $1 }')" ;; + Blocks_sent_to_initiator_) lbas_read="$(echo "${attr_value}" | awk '{ printf "%e\n", $1 }')" ;; + Blocks_received_from_initiator_) lbas_written="$(echo "${attr_value}" | awk '{ printf "%e\n", $1 }')" ;; + Accumulated_start-stop_cycles) power_cycle="$(echo "${attr_value}" | awk '{ printf "%e\n", $1 }')" ;; + Elements_in_grown_defect_list) grown_defects="$(echo "${attr_value}" | awk '{ printf "%e\n", $1 }')" ;; + esac + done + [ -n "$power_on" ] && echo "power_on_hours_raw_value{${labels},smart_id=\"9\"} ${power_on}" + [ -n "$temp_cel" ] && echo "temperature_celsius_raw_value{${labels},smart_id=\"194\"} ${temp_cel}" + [ -n "$lbas_read" ] && echo "total_lbas_read_raw_value{${labels},smart_id=\"242\"} ${lbas_read}" + [ -n "$lbas_written" ] && echo "total_lbas_written_raw_value{${labels},smart_id=\"241\"} ${lbas_written}" + [ -n "$power_cycle" ] && echo "power_cycle_count_raw_value{${labels},smart_id=\"12\"} ${power_cycle}" + [ -n "$grown_defects" ] && echo "grown_defects_count_raw_value{${labels},smart_id=\"-1\"} ${grown_defects}" +} + +parse_smartctl_info() { + local -i smart_available=0 smart_enabled=0 smart_healthy= + local disk="$1" disk_type="$2" + local model_family='' device_model='' serial_number='' fw_version='' vendor='' product='' revision='' lun_id='' + while read -r line; do + info_type="$(echo "${line}" | cut -f1 -d: | tr ' ' '_')" + info_value="$(echo "${line}" | cut -f2- -d: | sed 's/^ \+//g' | sed 's/"/\\"/')" + case "${info_type}" in + Model_Family) model_family="${info_value}" ;; + Device_Model|Model_Number) device_model="${info_value}" ;; + Serial_Number|Serial_number) serial_number="${info_value}" ;; + Firmware_Version) fw_version="${info_value}" ;; + Vendor) vendor="${info_value}" ;; + Product) product="${info_value}" ;; + Revision) revision="${info_value}" ;; + Logical_Unit_id) lun_id="${info_value}" ;; + esac + if [[ "${info_type}" == 'SMART_support_is' ]]; then + case "${info_value:0:7}" in + Enabled) smart_available=1; smart_enabled=1 ;; + Availab) smart_available=1; smart_enabled=0 ;; + Unavail) smart_available=0; smart_enabled=0 ;; + esac + fi + if [[ "${info_type}" == 'SMART_overall-health_self-assessment_test_result' ]]; then + case "${info_value:0:6}" in + PASSED) smart_healthy=1 ;; + *) smart_healthy=0 ;; + esac + elif [[ "${info_type}" == 'SMART_Health_Status' ]]; then + case "${info_value:0:2}" in + OK) smart_healthy=1 ;; + *) smart_healthy=0 ;; + esac + fi + done + echo "device_info{disk=\"${disk}\",type=\"${disk_type}\",vendor=\"${vendor}\",product=\"${product}\",revision=\"${revision}\",lun_id=\"${lun_id}\",model_family=\"${model_family}\",device_model=\"${device_model}\",serial_number=\"${serial_number}\",firmware_version=\"${fw_version}\"} 1" + echo "device_smart_available{disk=\"${disk}\",type=\"${disk_type}\"} ${smart_available}" + echo "device_smart_enabled{disk=\"${disk}\",type=\"${disk_type}\"} ${smart_enabled}" + [[ "${smart_healthy}" != "" ]] && echo "device_smart_healthy{disk=\"${disk}\",type=\"${disk_type}\"} ${smart_healthy}" +} + +output_format_awk="$( + cat <<'OUTPUTAWK' +BEGIN { v = "" } +v != $1 { + print "# HELP smartmon_" $1 " SMART metric " $1; + print "# TYPE smartmon_" $1 " gauge"; + v = $1 +} +{print "smartmon_" $0} +OUTPUTAWK +)" + +format_output() { + sort | + awk -F'{' "${output_format_awk}" +} + +smartctl_version="$(/usr/sbin/smartctl -V | head -n1 | awk '$1 == "smartctl" {print $2}')" + +echo "smartctl_version{version=\"${smartctl_version}\"} 1" | format_output + +if [[ "$(expr "${smartctl_version}" : '\([0-9]*\)\..*')" -lt 6 ]]; then + exit +fi + +device_list="$(/usr/sbin/smartctl --scan-open | awk '/^\/dev/{print $1 "|" $3}')" + +for device in ${device_list}; do + disk="$(echo "${device}" | cut -f1 -d'|')" + type="$(echo "${device}" | cut -f2 -d'|')" + active=1 + echo "smartctl_run{disk=\"${disk}\",type=\"${type}\"}" "$(TZ=UTC date '+%s')" + # Check if the device is in a low-power mode + /usr/sbin/smartctl -n standby -d "${type}" "${disk}" > /dev/null || active=0 + echo "device_active{disk=\"${disk}\",type=\"${type}\"}" "${active}" + # Skip further metrics to prevent the disk from spinning up + test ${active} -eq 0 && continue + # Get the SMART information and health + /usr/sbin/smartctl -i -H -d "${type}" "${disk}" | parse_smartctl_info "${disk}" "${type}" + # Get the SMART attributes + case ${type} in + sat) /usr/sbin/smartctl -A -d "${type}" "${disk}" | parse_smartctl_attributes "${disk}" "${type}" ;; + sat+megaraid*) /usr/sbin/smartctl -A -d "${type}" "${disk}" | parse_smartctl_attributes "${disk}" "${type}" ;; + scsi) /usr/sbin/smartctl -A -d "${type}" "${disk}" | parse_smartctl_scsi_attributes "${disk}" "${type}" ;; + megaraid*) /usr/sbin/smartctl -A -d "${type}" "${disk}" | parse_smartctl_scsi_attributes "${disk}" "${type}" ;; + nvme*) /usr/sbin/smartctl -A -d "${type}" "${disk}" | parse_smartctl_scsi_attributes "${disk}" "${type}" ;; + usbprolific) /usr/sbin/smartctl -A -d "${type}" "${disk}" | parse_smartctl_attributes "${disk}" "${type}" ;; + *) + (>&2 echo "disk type is not sat, scsi, nvme or megaraid but ${type}") + exit + ;; + esac +done | format_output diff --git a/roles/node_exporter/handlers/main.yml b/roles/node_exporter/handlers/main.yml new file mode 100644 index 0000000..5bfbd16 --- /dev/null +++ b/roles/node_exporter/handlers/main.yml @@ -0,0 +1,10 @@ +--- +- name: Restart node_exporter + ansible.builtin.service: + name: >- + {% if ansible_distribution == "OpenBSD" -%} + {{ "node_exporter" -}} + {% else -%} + {{ "prometheus-node-exporter" -}} + {% endif -%} + state: restarted diff --git a/roles/node_exporter/meta/main.yml b/roles/node_exporter/meta/main.yml new file mode 100644 index 0000000..ed212b9 --- /dev/null +++ b/roles/node_exporter/meta/main.yml @@ -0,0 +1,6 @@ +--- +dependencies: + - role: epel_repo + when: + - ansible_os_family == "RedHat" + - ansible_distribution != "Fedora" diff --git a/roles/node_exporter/tasks/main.yml b/roles/node_exporter/tasks/main.yml new file mode 100644 index 0000000..f1c0968 --- /dev/null +++ b/roles/node_exporter/tasks/main.yml @@ -0,0 +1,132 @@ +--- +- name: Install packages + ansible.builtin.package: + name: >- + {% if ansible_distribution in ["Fedora", "OpenBSD"] -%} + {{ "node_exporter" -}} + {% else -%} + {{ "golang-github-prometheus-node-exporter" -}} + {% endif -%} + state: installed + +- name: Allow prometheus user to read private key + ansible.builtin.user: + name: >- + {% if ansible_distribution == "OpenBSD" -%} + {{ "_nodeexporter" -}} + {% else -%} + {{ "prometheus" -}} + {% endif -%} + groups: hostkey + append: true + create_home: false + notify: Restart node_exporter + +- name: Create config directory + ansible.builtin.file: + path: /etc/node_exporter + state: directory + mode: "0755" + owner: root + group: "{{ ansible_wheel }}" + +- name: Create web-config + ansible.builtin.template: + dest: /etc/node_exporter/web-config.yml + src: web-config.yml.j2 + mode: "0644" + owner: root + group: "{{ ansible_wheel }}" + notify: Restart node_exporter + +- name: Create textfile collector directory + ansible.builtin.file: + path: /var/db/node-exporter + state: directory + mode: 0755 + owner: _nodeexporter + group: _nodeexporter + when: ansible_os_family == "OpenBSD" + +- name: Create directory for textfile collector scripts + ansible.builtin.file: + path: /usr/local/libexec/node-exporter + state: directory + mode: 0755 + owner: root + group: "{{ ansible_wheel }}" + +- name: Add script for running textfile collector scripts + ansible.builtin.copy: + dest: /usr/local/sbin/node-exporter-run-textfile-collector + src: node-exporter-run-textfile-collector.sh + mode: 0755 + owner: root + group: "{{ ansible_wheel }}" + +- name: Add cron job for running textfile collector scripts + ansible.builtin.cron: + name: node-exporter-run-textfile-collector + job: /usr/local/sbin/node-exporter-run-textfile-collector + minute: "*/10" + +- name: Modify config (pre 1.5.0) + ansible.builtin.lineinfile: + path: /etc/default/prometheus-node-exporter + regexp: "^ARGS=" + line: >- + ARGS="--collector.filesystem.ignored-mount-points='^/(dev|proc|sys|run/(user|credentials/systemd-.+))($|/)' + --collector.netclass.ignored-devices='^(br-|docker|veth).+$' + --collector.netdev.device-exclude='^(br-|docker|veth).+$' + --web.config=/etc/node_exporter/web-config.yml + --collector.textfile.directory=/var/lib/prometheus/node-exporter" + notify: Restart node_exporter + when: + - ansible_os_family == "RedHat" + - ansible_distribution != "Fedora" + +- name: Modify config + ansible.builtin.lineinfile: + path: /etc/default/prometheus-node-exporter + regexp: "^ARGS=" + line: >- + ARGS="--collector.filesystem.ignored-mount-points='^/(dev|proc|sys|run/(user|credentials/systemd-.+))($|/)' + --collector.netclass.ignored-devices='^(br-|docker|veth).+$' + --collector.netdev.device-exclude='^(br-|docker|veth).+$' + --web.config.file=/etc/node_exporter/web-config.yml + --collector.textfile.directory=/var/lib/prometheus/node-exporter" + notify: Restart node_exporter + when: + - ansible_distribution == "Fedora" + +- name: Install disk and raid monitoring scripts + ansible.builtin.copy: + dest: "/usr/local/libexec/node-exporter/{{ item }}" + src: "{{ item }}" + mode: "0755" + owner: root + group: "{{ ansible_wheel }}" + with_items: + - md_info.sh + - smartmon.sh + when: + - ansible_virtualization_role == "host" + - ansible_os_family == "RedHat" + +- name: Enable service + ansible.builtin.service: + name: node_exporter + state: started + enabled: true + arguments: >- + --web.config.file=/etc/node_exporter/web-config.yml + --collector.textfile.directory=/var/db/node-exporter + notify: Restart node_exporter + when: ansible_os_family == "OpenBSD" + +- name: Enable service + ansible.builtin.service: + name: prometheus-node-exporter + state: started + enabled: true + when: ansible_os_family == "RedHat" diff --git a/roles/node_exporter/templates/web-config.yml.j2 b/roles/node_exporter/templates/web-config.yml.j2 new file mode 100644 index 0000000..07cdaf3 --- /dev/null +++ b/roles/node_exporter/templates/web-config.yml.j2 @@ -0,0 +1,7 @@ +--- +tls_server_config: + key_file: {{ tls_private }}/{{ inventory_hostname }}.key + cert_file: {{ tls_certs }}/{{ inventory_hostname }}.crt + client_ca_file: {{ tls_certs }}/ca.crt + client_auth_type: RequireAndVerifyClientCert + min_version: TLS13 diff --git a/roles/nodered/defaults/main.yml b/roles/nodered/defaults/main.yml new file mode 100644 index 0000000..bf68f6d --- /dev/null +++ b/roles/nodered/defaults/main.yml @@ -0,0 +1,2 @@ +--- +nodered_version: latest diff --git a/roles/nodered/handlers/main.yml b/roles/nodered/handlers/main.yml new file mode 100644 index 0000000..073db56 --- /dev/null +++ b/roles/nodered/handlers/main.yml @@ -0,0 +1,6 @@ +--- +- name: Restart nodered + ansible.builtin.systemd_service: + name: nodered-container + state: restarted + daemon_reload: true diff --git a/roles/nodered/meta/main.yml b/roles/nodered/meta/main.yml new file mode 100644 index 0000000..305b1b2 --- /dev/null +++ b/roles/nodered/meta/main.yml @@ -0,0 +1,4 @@ +--- +dependencies: + - {role: nginx} + - {role: podman} diff --git a/roles/nodered/tasks/main.yml b/roles/nodered/tasks/main.yml new file mode 100644 index 0000000..011e6f3 --- /dev/null +++ b/roles/nodered/tasks/main.yml @@ -0,0 +1,80 @@ +--- +- name: Create group + ansible.builtin.group: + name: nodered + +- name: Create user + ansible.builtin.user: + name: nodered + comment: Podman NodeRed + group: nodered + shell: /sbin/nologin + +- name: Enable user lingering + ansible.builtin.command: + argv: + - loginctl + - enable-linger + - nodered + creates: /var/lib/systemd/linger/nodered + +- name: Fix SELinux contexts from config directory + community.general.sefcontext: + path: /export/nodered(/.*)? + setype: container_file_t + when: ansible_selinux_python_present + +- name: Get subgid number + ansible.builtin.command: + argv: + - awk + - "-F:" + - '{ if ($1 == "nodered") print $2 + 999 }' + - /etc/subgid + changed_when: false + register: subgid + +- name: Create config directory + ansible.builtin.file: + path: /export/nodered + state: directory + mode: "0770" + owner: root + group: "{{ subgid.stdout }}" + setype: _default + +- name: Link config directory + ansible.builtin.file: + dest: /srv/nodered + src: /export/nodered + state: link + owner: root + group: "{{ ansible_wheel }}" + follow: false + +- name: Create service file + ansible.builtin.template: + dest: /etc/systemd/system/nodered-container.service + src: nodered-container.service.j2 + mode: "0644" + owner: root + group: "{{ ansible_wheel }}" + notify: Restart nodered + +- name: Enable service + ansible.builtin.service: + name: nodered-container + state: started + enabled: true + +- name: Copy nginx config + ansible.builtin.copy: + dest: "/etc/nginx/conf.d/{{ inventory_hostname }}/00-nodered.conf" + content: | + location /nodered/ { + proxy_pass http://127.0.0.1:8012/; + } + mode: "0644" + owner: root + group: "{{ ansible_wheel }}" + notify: Restart nginx diff --git a/roles/nodered/templates/nodered-container.service.j2 b/roles/nodered/templates/nodered-container.service.j2 new file mode 100644 index 0000000..fa188a7 --- /dev/null +++ b/roles/nodered/templates/nodered-container.service.j2 @@ -0,0 +1,18 @@ +[Unit] +Description=NodeRed Container +Wants=network-online.target +After=network-online.target + +[Service] +User=nodered +ExecStart=/usr/bin/podman run \ + --rm -p 127.0.0.1:8012:1880 \ + --name nodered \ + --env TZ=Europe/Helsinki \ + --volume /srv/nodered:/data:rw \ + docker.io/nodered/node-red:{{ nodered_version }} +ExecStop=/usr/bin/podman stop --ignore nodered +ExecStopPost=/usr/bin/podman rm -f --ignore nodered + +[Install] +WantedBy=multi-user.target diff --git a/roles/nsd/tasks/main.yml b/roles/nsd/tasks/main.yml index 930a01d..da21b4f 100644 --- a/roles/nsd/tasks/main.yml +++ b/roles/nsd/tasks/main.yml @@ -3,7 +3,7 @@ ansible.builtin.copy: dest: "{{ tls_private }}/{{ nsd_server }}.key" src: "{{ item }}" - mode: 0600 + mode: "0600" owner: root group: "{{ ansible_wheel }}" with_first_found: @@ -17,7 +17,7 @@ ansible.builtin.copy: dest: "{{ tls_certs }}/{{ nsd_server }}.crt" src: "{{ item }}" - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" with_first_found: @@ -31,7 +31,7 @@ ansible.builtin.template: src: nsd.conf.j2 dest: /var/nsd/etc/nsd.conf - mode: 0640 + mode: "0640" owner: root group: _nsd notify: Restart nsd @@ -40,9 +40,10 @@ ansible.builtin.copy: dest: "/var/nsd/zones/master/{{ item | replace('/', '-') }}" src: "/srv/dns/{{ item | replace('/', '-') }}" - mode: 0640 + mode: "0640" owner: root group: _nsd + validate: "nsd-checkzone '{{ item }}' '%s'" tags: dns notify: Restart nsd with_items: "{{ nsd_zones }}" diff --git a/roles/nsd/templates/nsd.conf.j2 b/roles/nsd/templates/nsd.conf.j2 index 60251c1..9e8afec 100644 --- a/roles/nsd/templates/nsd.conf.j2 +++ b/roles/nsd/templates/nsd.conf.j2 @@ -7,10 +7,10 @@ server: server-count: {{ ansible_processor_count }} verbosity: 2 - interface: ::0@53 - interface: 0.0.0.0@53 - interface: ::0@853 - interface: 0.0.0.0@853 +{% for ip in ansible_all_ipv4_addresses + ansible_all_ipv6_addresses %} + interface: {{ ip }}@53 + interface: {{ ip }}@853 +{% endfor %} tls-service-key: {{ tls_private }}/{{ nsd_server }}.key tls-service-pem: {{ tls_certs }}/{{ nsd_server }}.crt diff --git a/roles/openbgpd/tasks/main.yml b/roles/openbgpd/tasks/main.yml index 94e78fe..736ce90 100644 --- a/roles/openbgpd/tasks/main.yml +++ b/roles/openbgpd/tasks/main.yml @@ -3,7 +3,7 @@ ansible.builtin.copy: dest: /etc/bgpd.conf src: "{{ ansible_private }}/files/bgpd/bgpd.conf.{{ inventory_hostname }}" - mode: 0600 + mode: "0600" owner: root group: "{{ ansible_wheel }}" notify: Restart bgpd diff --git a/roles/opendkim/defaults/main.yml b/roles/opendkim/defaults/main.yml new file mode 100644 index 0000000..ae208c6 --- /dev/null +++ b/roles/opendkim/defaults/main.yml @@ -0,0 +1,2 @@ +--- +opendkim_selector: default diff --git a/roles/opendkim/files/keystore.Makefile b/roles/opendkim/files/keystore.Makefile new file mode 100644 index 0000000..1a04593 --- /dev/null +++ b/roles/opendkim/files/keystore.Makefile @@ -0,0 +1,28 @@ +TARGETS := $(shell { \ + if [ $$(date +%m) -lt 6 ]; then \ + echo "$$(date +%Y)0101.key $$(date +%Y)0601.key" ; \ + else \ + echo "$$(date +%Y)0601.key $$(($$(date +%Y) + 1))0101.key" ; \ + fi \ + }) + +all: $(TARGETS) + +%.key: + @set -eu ; \ + openssl genrsa -out "$@" 2048 ; \ + chgrp opendkim "$@" ; \ + chmod 0640 "$@" ; \ + echo ; \ + data="$$(printf "v=DKIM1; k=rsa; p=%s" \ + "$$(openssl rsa -in "$@" -pubout -outform der 2>/dev/null | openssl base64 -A)")" ; \ + pos=0 ; \ + printf "%s._domainkey\tIN\tTXT\t" "$$(echo "$@" | cut -d. -f1)" ; \ + while true ; do \ + printf "\"%s\"" \ + "$$(echo "$$data" | cut -c $$((pos + 1))-$$((pos + 254)))" ; \ + pos="$$((pos + 254))" ; \ + [ $${#data} -gt $$pos ] || break ; \ + printf " " ; \ + done ; \ + echo diff --git a/roles/opendkim/handlers/main.yml b/roles/opendkim/handlers/main.yml new file mode 100644 index 0000000..e98da1b --- /dev/null +++ b/roles/opendkim/handlers/main.yml @@ -0,0 +1,5 @@ +--- +- name: Restart opendkim + ansible.builtin.service: + name: opendkim + state: restarted diff --git a/roles/opendkim/tasks/main.yml b/roles/opendkim/tasks/main.yml new file mode 100644 index 0000000..7c1001a --- /dev/null +++ b/roles/opendkim/tasks/main.yml @@ -0,0 +1,85 @@ +--- +- name: Install packages + ansible.builtin.package: + name: opendkim + state: installed + +- name: Fix SELinux contexts from keystore + community.general.sefcontext: + path: "/export/dkim(/.*)?" + setype: etc_t + +- name: Create keystore + ansible.builtin.file: + path: /export/dkim + state: directory + mode: "0710" + owner: root + group: opendkim + setype: _default + +- name: Link keystore + ansible.builtin.file: + dest: /srv/dkim + src: /export/dkim + state: link + owner: root + group: "{{ ansible_wheel }}" + follow: false + +- name: Add keystore Makefile + ansible.builtin.copy: + dest: /srv/dkim/Makefile + src: keystore.Makefile + mode: "0600" + owner: root + group: "{{ ansible_wheel }}" + setype: _default + +- name: Set selector + ansible.builtin.lineinfile: + path: /etc/opendkim.conf + regexp: '^(# )?Selector\s' + line: "Selector\t{{ opendkim_selector }}" + notify: Restart opendkim + +- name: Set key file path + ansible.builtin.lineinfile: + path: /etc/opendkim.conf + regexp: '^(# )?KeyFile\s' + line: "KeyFile\t/srv/dkim/{{ opendkim_selector }}.key" + notify: Restart opendkim + +- name: Enable signing and verifying messages + ansible.builtin.lineinfile: + path: /etc/opendkim.conf + regexp: '^(# )?Mode\s' + line: "Mode\tsv" + notify: Restart opendkim + +- name: Configure signing domains + ansible.builtin.lineinfile: + path: /etc/opendkim.conf + regexp: '^(# )?Domain\s' + line: "Domain\t{{ mail_domain }}" + notify: Restart opendkim + +- name: Configure report address + ansible.builtin.lineinfile: + path: /etc/opendkim.conf + regexp: '^(# )?ReportAddress\s' + line: "ReportAddress\tpostmaster@{{ mail_domain }}" + notify: Restart opendkim + +- name: Don't add DKIM-Filter header + ansible.builtin.lineinfile: + path: /etc/opendkim.conf + regexp: '^(# )?SoftwareHeader\s' + line: "SoftwareHeader\tno" + notify: Restart opendkim + +- name: Enable service + ansible.builtin.service: + name: opendkim + state: started + enabled: true diff --git a/roles/opensmtpd/tasks/main.yml b/roles/opensmtpd/tasks/main.yml index 243a1e0..40e1891 100644 --- a/roles/opensmtpd/tasks/main.yml +++ b/roles/opensmtpd/tasks/main.yml @@ -3,7 +3,7 @@ ansible.builtin.template: src: smtpd.conf.j2 dest: /etc/mail/smtpd.conf - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" notify: Restart opensmtpd @@ -12,7 +12,7 @@ ansible.builtin.copy: content: "{{ mail_domain }}\n" dest: /etc/mail//mailname - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" notify: Restart opensmtpd diff --git a/roles/openvpn/files/hostname.tap0 b/roles/openvpn/files/hostname.tap0 index cd1c353..2b44eb9 100644 --- a/roles/openvpn/files/hostname.tap0 +++ b/roles/openvpn/files/hostname.tap0 @@ -1,2 +1,2 @@ up -!/usr/local/sbin/openvpn --daemon --config /etc/openvpn/tap0.conf +!/sbin/route -T 1 exec /usr/local/sbin/openvpn --daemon --config /etc/openvpn/tap0.conf diff --git a/roles/openvpn/tasks/main.yml b/roles/openvpn/tasks/main.yml index 7f1edca..84b8d2b 100644 --- a/roles/openvpn/tasks/main.yml +++ b/roles/openvpn/tasks/main.yml @@ -8,7 +8,7 @@ ansible.builtin.file: path: /var/openvpn state: directory - mode: 0750 + mode: "0750" owner: root group: _openvpn @@ -16,7 +16,7 @@ ansible.builtin.file: path: /var/openvpn/tmp state: directory - mode: 0770 + mode: "0770" owner: _openvpn group: _openvpn @@ -24,7 +24,7 @@ ansible.builtin.file: path: /etc/openvpn state: directory - mode: 0755 + mode: "0755" owner: root group: "{{ ansible_wheel }}" @@ -32,7 +32,7 @@ ansible.builtin.file: path: /etc/openvpn/keys state: directory - mode: 0700 + mode: "0700" owner: root group: "{{ ansible_wheel }}" @@ -40,7 +40,7 @@ ansible.builtin.copy: src: "{{ ansible_private }}/files/openvpn/{{ inventory_hostname }}.key" dest: /etc/openvpn/keys/tap0.key - mode: 0600 + mode: "0600" owner: root group: "{{ ansible_wheel }}" @@ -48,7 +48,7 @@ ansible.builtin.copy: src: "{{ ansible_private }}/files/openvpn/{{ inventory_hostname }}.conf" dest: /etc/openvpn/tap0.conf - mode: 0600 + mode: "0600" owner: root group: "{{ ansible_wheel }}" @@ -56,6 +56,6 @@ ansible.builtin.copy: src: hostname.tap0 dest: /etc/hostname.tap0 - mode: 0600 + mode: "0600" owner: root group: "{{ ansible_wheel }}" diff --git a/roles/pf/files/pf.conf.gw_fsol b/roles/pf/files/pf.conf.gw_fsol index c6bfb1b..48215c0 100644 --- a/roles/pf/files/pf.conf.gw_fsol +++ b/roles/pf/files/pf.conf.gw_fsol @@ -30,9 +30,9 @@ pass quick inet6 proto icmp6 antispoof for lo0 antispoof for vio0 -# admin connection and munin (internal) +# admin connection and node_exporter (internal) pass in quick on $int_if proto tcp from $int_net to self port ssh keep state (no-sync) -pass in quick on $int_if proto tcp from $int_net to self port 4949 keep state (no-sync) +pass in quick on $int_if proto tcp from $int_net to self port 9100 keep state (no-sync) # internal network block in quick from any to self diff --git a/roles/pf/files/pf.conf.gw_home b/roles/pf/files/pf.conf.gw_home index a71029d..3f211fb 100644 --- a/roles/pf/files/pf.conf.gw_home +++ b/roles/pf/files/pf.conf.gw_home @@ -39,14 +39,15 @@ antispoof for lo0 antispoof for vio0 antispoof for vio1 -# admin connection (internal, fsol and arc office) +# admin connection (internal, arcsec office, dmz, lan) pass in quick on $int_if proto tcp from $int_net to self port ssh pass in quick on $ext_if proto tcp from 37.35.86.64/29 to self port ssh pass in quick on $ext_if proto tcp from 37.16.96.144/28 to self port ssh -pass in quick on $ext_if proto tcp from 81.175.155.142/32 to self port ssh +pass in quick on $ext_if proto tcp from 212.149.225.198/32 to self port ssh -# munin from internal network -pass in quick on $int_if proto tcp from $int_net to self port 4949 +# node_exporter and unbound_exporter from internal network +pass in quick on $int_if proto tcp from $int_net to self port 9100 +pass in quick on $int_if proto tcp from $int_net to self port 9167 # allow dns queries from internal net pass in quick on $int_if proto { tcp, udp } from $int_net to self port domain diff --git a/roles/pf/tasks/main.yml b/roles/pf/tasks/main.yml index 578a0d6..588dac6 100644 --- a/roles/pf/tasks/main.yml +++ b/roles/pf/tasks/main.yml @@ -3,7 +3,7 @@ ansible.builtin.copy: src: "{{ firewall_src }}" dest: /etc/pf.conf - mode: 0600 + mode: "0600" owner: root group: "{{ ansible_wheel }}" validate: pfctl -N -f %s @@ -14,7 +14,7 @@ ansible.builtin.template: src: pf.conf.j2 dest: /etc/pf.conf - mode: 0600 + mode: "0600" owner: root group: "{{ ansible_wheel }}" validate: pfctl -N -f %s diff --git a/roles/php4dvd/handlers/main.yml b/roles/php4dvd/handlers/main.yml new file mode 100644 index 0000000..bc94087 --- /dev/null +++ b/roles/php4dvd/handlers/main.yml @@ -0,0 +1,17 @@ +--- +- name: Rebuild php4dvd-container + ansible.builtin.command: + argv: + - podman + - build + - -t + - php4dvd + - /usr/local/src/docker-php4dvd + become: true + become_user: php4dvd + notify: Restart php4dvd-container + +- name: Restart php4dvd-container + ansible.builtin.service: + name: php4dvd-container + state: restarted diff --git a/roles/php4dvd/meta/main.yml b/roles/php4dvd/meta/main.yml new file mode 100644 index 0000000..b8e2a3e --- /dev/null +++ b/roles/php4dvd/meta/main.yml @@ -0,0 +1,5 @@ +--- +dependencies: + - {role: git} + - {role: nginx} + - {role: podman} diff --git a/roles/php4dvd/tasks/main.yml b/roles/php4dvd/tasks/main.yml new file mode 100644 index 0000000..749a032 --- /dev/null +++ b/roles/php4dvd/tasks/main.yml @@ -0,0 +1,71 @@ +--- +- name: Create group + ansible.builtin.group: + name: php4dvd + +- name: Create user + ansible.builtin.user: + name: php4dvd + comment: Podman pphp4dvd + group: php4dvd + shell: /sbin/nologin + +- name: Enable user lingering + ansible.builtin.command: + argv: + - loginctl + - enable-linger + - php4dvd + creates: /var/lib/systemd/linger/php4dvd + +- name: Copy host key + ansible.builtin.copy: + dest: "{{ tls_private }}/php4dvd.key" + src: "{{ tls_private }}/{{ inventory_hostname }}.key" + mode: "0640" + owner: root + group: php4dvd + remote_src: true + +- name: Get container source + ansible.builtin.git: + dest: /usr/local/src/docker-php4dvd + repo: https://github.com/foo-sh/docker-php4dvd.git + update: true + version: master + notify: Rebuild php4dvd-container + +- name: Create service file + ansible.builtin.template: + dest: /etc/systemd/system/php4dvd-container.service + src: php4dvd-container.service.j2 + mode: "0644" + owner: root + group: "{{ ansible_wheel }}" + +- name: Create service config + ansible.builtin.template: + dest: /etc/sysconfig/php4dvd-container + src: php4dvd-container.sysconfig.j2 + mode: "0600" + owner: root + group: "{{ ansible_wheel }}" + notify: Restart php4dvd-container + +- name: Enable service + ansible.builtin.service: + name: php4dvd-container + state: started + enabled: true + +- name: Copy nginx config + ansible.builtin.copy: + dest: "/etc/nginx/conf.d/{{ inventory_hostname }}/php4dvd-container.conf" + content: | + location /php4dvd { + proxy_pass http://127.0.0.1:8005/; + } + mode: "0644" + owner: root + group: "{{ ansible_wheel }}" + notify: Restart nginx diff --git a/roles/php4dvd/templates/php4dvd-container.service.j2 b/roles/php4dvd/templates/php4dvd-container.service.j2 new file mode 100644 index 0000000..af646cb --- /dev/null +++ b/roles/php4dvd/templates/php4dvd-container.service.j2 @@ -0,0 +1,22 @@ +[Unit] +Description=php4dvd Container +Wants=network-online.target +After=network-online.target + +[Service] +User=php4dvd +EnvironmentFile=/etc/sysconfig/php4dvd-container +ExecStart=/usr/bin/podman run \ + --rm -p 127.0.0.1:8005:80 \ + --name php4dvd \ + --env PHP4DVD_* \ + --volume={{ tls_certs }}/ca.crt:/etc/ssl/certs/ca.crt:ro \ + --volume={{ tls_certs }}/{{ inventory_hostname }}.crt:/etc/ssl/certs/{{ inventory_hostname }}.crt:ro \ + --volume={{ tls_private }}/php4dvd.key:/etc/ssl/private/{{ inventory_hostname }}.key:ro \ + --volume /export/volumes/php4dvd:/var/www/html/movies:rw,Z \ + php4dvd:latest +ExecStop=/usr/bin/podman stop --ignore php4dvd +ExecStopPost=/usr/bin/podman rm -f --ignore php4dvd + +[Install] +WantedBy=multi-user.target diff --git a/roles/php4dvd/templates/php4dvd-container.sysconfig.j2 b/roles/php4dvd/templates/php4dvd-container.sysconfig.j2 new file mode 100644 index 0000000..79c274b --- /dev/null +++ b/roles/php4dvd/templates/php4dvd-container.sysconfig.j2 @@ -0,0 +1,8 @@ +PHP4DVD_DB_HOST=sqldb02.home.foo.sh +PHP4DVD_DB_NAME=php4dvd +PHP4DVD_DB_USER=php4dvd +PHP4DVD_DB_PASS={{ php4dvd_mysql_pass }} +PHP4DVD_DB_KEY=/etc/ssl/private/{{ inventory_hostname }}.key +PHP4DVD_DB_CERT=/etc/ssl/certs/{{ inventory_hostname }}.crt +PHP4DVD_DB_CACERT=/etc/ssl/certs/ca.crt +PHP4DVD_USER_GUESTVIEW=true diff --git a/roles/pki/files/mtree.patch b/roles/pki/files/mtree.patch new file mode 100644 index 0000000..17ce41e --- /dev/null +++ b/roles/pki/files/mtree.patch @@ -0,0 +1,11 @@ +--- 4.4BSD.dist.orig Fri Dec 22 17:31:46 2023 ++++ 4.4BSD.dist Fri Dec 22 17:32:00 2023 +@@ -105,7 +105,7 @@ + + # ./etc/ssl + ssl +- private uname=root mode=0700 ++ private gname=hostkey uname=root mode=0750 + .. + .. + diff --git a/roles/pki/tasks/main.yml b/roles/pki/tasks/main.yml index 020211e..90d160e 100644 --- a/roles/pki/tasks/main.yml +++ b/roles/pki/tasks/main.yml @@ -8,7 +8,7 @@ ansible.builtin.copy: src: "/srv/ca/certs/ca.crt" dest: "{{ tls_certs }}/ca.crt" - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" @@ -24,15 +24,22 @@ delegate_to: localhost register: result changed_when: false + check_mode: false - name: Store ca certificate hash ansible.builtin.set_fact: pki_cacert_hash: "{{ result.stdout }}" +- name: Patch mtree to set correct permissions on /etc/ssl/private + ansible.posix.patch: + dest: /etc/mtree/4.4BSD.dist + src: mtree.patch + when: ansible_system == "OpenBSD" + - name: Fix private key directory permissions ansible.builtin.file: path: "{{ tls_private }}" - mode: 0750 + mode: "0750" owner: root group: hostkey when: ansible_system == "OpenBSD" @@ -41,7 +48,7 @@ ansible.builtin.copy: src: "/srv/ca/certs/hosts/{{ inventory_hostname }}.crt" dest: "{{ tls_certs }}/{{ inventory_hostname }}.crt" - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" @@ -56,7 +63,7 @@ ' {{ tls_certs }}/{{ inventory_hostname }}.crt dest: /etc/ansible/facts.d/ansible_certificate.fact - mode: 0755 + mode: "0755" owner: root group: "{{ ansible_wheel }}" @@ -67,13 +74,14 @@ - "{{ tls_certs }}/{{ inventory_hostname }}.crt" - "{{ tls_certs }}/ca.crt" changed_when: false + check_mode: false register: pki_host_fullchain - name: Copy full chain certificate file ansible.builtin.copy: dest: "{{ tls_certs }}/{{ inventory_hostname }}-fullchain.crt" content: "{{ pki_host_fullchain.stdout }}" - mode: 0640 + mode: "0640" owner: root group: "{{ ansible_wheel }}" @@ -81,6 +89,6 @@ ansible.builtin.copy: src: "/srv/ca/private/{{ inventory_hostname }}.key" dest: "{{ tls_private }}/{{ inventory_hostname }}.key" - mode: 0640 + mode: "0640" owner: root group: hostkey diff --git a/roles/podman/meta/main.yml b/roles/podman/meta/main.yml deleted file mode 100644 index b95ceec..0000000 --- a/roles/podman/meta/main.yml +++ /dev/null @@ -1,3 +0,0 @@ ---- -dependencies: - - {role: nginx/server} diff --git a/roles/podman/tasks/main.yml b/roles/podman/tasks/main.yml index f574e4c..93660dd 100644 --- a/roles/podman/tasks/main.yml +++ b/roles/podman/tasks/main.yml @@ -14,7 +14,7 @@ ansible.builtin.copy: dest: /usr/local/share/selinux/podman-certs.pp src: podman-certs.pp - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" diff --git a/roles/prometheus/handlers/main.yml b/roles/prometheus/handlers/main.yml new file mode 100644 index 0000000..690e0bd --- /dev/null +++ b/roles/prometheus/handlers/main.yml @@ -0,0 +1,5 @@ +--- +- name: Restart prometheus + ansible.builtin.service: + name: prometheus + state: restarted diff --git a/roles/prometheus/meta/main.yml b/roles/prometheus/meta/main.yml new file mode 100644 index 0000000..1e5084e --- /dev/null +++ b/roles/prometheus/meta/main.yml @@ -0,0 +1,4 @@ +--- +dependencies: + - {role: epel_repo} + - {role: nginx} diff --git a/roles/prometheus/tasks/main.yml b/roles/prometheus/tasks/main.yml new file mode 100644 index 0000000..eb47818 --- /dev/null +++ b/roles/prometheus/tasks/main.yml @@ -0,0 +1,100 @@ +--- +- name: Create group + ansible.builtin.group: + name: prometheus + gid: 305 + +- name: Create user + ansible.builtin.user: + name: prometheus + comment: Service Prometheus + createhome: false + group: prometheus + home: /var/empty + shell: /sbin/nologin + uid: 305 + +- name: Install packages + ansible.builtin.package: + name: golang-github-prometheus + state: installed + +- name: Create data directory + ansible.builtin.file: + path: /export/prometheus + state: directory + mode: "0770" + owner: root + group: prometheus + +- name: Link data directory + ansible.builtin.file: + path: /srv/prometheus + src: /export/prometheus + state: link + owner: root + group: "{{ ansible_wheel }}" + follow: false + +- name: Configure startup options + ansible.builtin.lineinfile: + path: /etc/default/prometheus + regexp: "^ARGS=" + line: >- + ARGS="--config.file=/etc/prometheus/prometheus.yml + --log.level=info + --storage.tsdb.path=/srv/prometheus + --storage.tsdb.retention.time=365d + --web.console.libraries=/usr/local/share/prometheus/console_libraries" + notify: Restart prometheus + +- name: Create configuration + ansible.builtin.template: + dest: /etc/prometheus/prometheus.yml + src: prometheus.yml.j2 + mode: "0640" + owner: root + group: prometheus + notify: Restart prometheus + +- name: Create host config directory + ansible.builtin.file: + path: /etc/prometheus/node.d + state: directory + mode: "0750" + owner: root + group: prometheus + +- name: Create host configs + ansible.builtin.template: + dest: "/etc/prometheus/node.d/{{ item }}.json" + src: node.json.j2 + mode: "0640" + owner: root + group: prometheus + notify: Restart prometheus + with_items: "{{ groups['all'] }}" + +- name: Enable service + ansible.builtin.service: + name: prometheus + state: started + enabled: true + +- name: Allow nginx to connect prometheus + ansible.posix.seboolean: + name: httpd_can_network_connect + state: true + persistent: true + +- name: Copy nginx config + ansible.builtin.copy: + dest: "/etc/nginx/conf.d/{{ inventory_hostname }}/prometheus.conf" + content: | + location / { + proxy_pass http://127.0.0.1:9090; + } + mode: "0644" + owner: root + group: "{{ ansible_wheel }}" + notify: Restart nginx diff --git a/roles/prometheus/templates/node.json.j2 b/roles/prometheus/templates/node.json.j2 new file mode 100644 index 0000000..0f4e396 --- /dev/null +++ b/roles/prometheus/templates/node.json.j2 @@ -0,0 +1,10 @@ +[ + { + "labels": { + "instance": "{{ item }}" + }, + "targets": [ + "{{ item }}:9100" + ] + } +] diff --git a/roles/prometheus/templates/prometheus.yml.j2 b/roles/prometheus/templates/prometheus.yml.j2 new file mode 100644 index 0000000..74aa03f --- /dev/null +++ b/roles/prometheus/templates/prometheus.yml.j2 @@ -0,0 +1,82 @@ +--- +global: + scrape_interval: 1m + scrape_timeout: 10s + evaluation_interval: 1m + +scrape_configs: + - job_name: prometheus + static_configs: + - targets: + - "127.0.0.1:9090" + + - job_name: mysqld + scheme: https + tls_config: + ca_file: "{{ tls_certs }}/ca.crt" + key_file: "{{ tls_private }}/{{ inventory_hostname }}.key" + cert_file: "{{ tls_certs }}/{{ inventory_hostname }}.crt" + static_configs: + - targets: +{% for host in groups['sqldb'] %} + - {{ host }}:3306 +{% endfor %} + relabel_configs: + - source_labels: [__address__] + target_label: __param_target + - source_labels: [__param_target] + target_label: instance + - target_label: __address__ + replacement: {{ inventory_hostname }}:9104 + + - job_name: nginx + scheme: https + tls_config: + ca_file: "{{ tls_certs }}/ca.crt" + key_file: "{{ tls_private }}/{{ inventory_hostname }}.key" + cert_file: "{{ tls_certs }}/{{ inventory_hostname }}.crt" + static_configs: + - targets: + - {{ inventory_hostname }}:9113 + + - job_name: snmp + scheme: https + tls_config: + ca_file: "{{ tls_certs }}/ca.crt" + key_file: "{{ tls_private }}/{{ inventory_hostname }}.key" + cert_file: "{{ tls_certs }}/{{ inventory_hostname }}.crt" + static_configs: + - targets: + - 172.20.25.102 + metrics_path: /snmp + params: + auth: [public_v2] + module: [if_mib] + relabel_configs: + - source_labels: [__address__] + target_label: __param_target + - source_labels: [__param_target] + target_label: instance + - target_label: __address__ + replacement: nms.home.foo.sh:9116 + + - job_name: unbound + scheme: https + tls_config: + ca_file: "{{ tls_certs }}/ca.crt" + key_file: "{{ tls_private }}/{{ inventory_hostname }}.key" + cert_file: "{{ tls_certs }}/{{ inventory_hostname }}.crt" + static_configs: + - targets: + - dna-gw01.home.foo.sh:9167 + - dna-gw02.home.foo.sh:9167 + + - job_name: node + scheme: https + tls_config: + ca_file: "{{ tls_certs }}/ca.crt" + key_file: "{{ tls_private }}/{{ inventory_hostname }}.key" + cert_file: "{{ tls_certs }}/{{ inventory_hostname }}.crt" + file_sd_configs: + - files: + - /etc/prometheus/node.d/*.json diff --git a/roles/rclone/templates/rclone-sync.sh.j2 b/roles/rclone/files/rclone-sync.sh similarity index 70% rename from roles/rclone/templates/rclone-sync.sh.j2 rename to roles/rclone/files/rclone-sync.sh index a7aadb6..40323ce 100755 --- a/roles/rclone/templates/rclone-sync.sh.j2 +++ b/roles/rclone/files/rclone-sync.sh @@ -1,15 +1,21 @@ #!/bin/sh -set -u +set -eu umask 027 -TARGET="{{ destination }}" -CONFIG="/etc/rclone/rclone.conf" -LOGDIR="/var/log/rclone" +SERVICE="$(whoami)" + +TARGET="/srv/${SERVICE}" +CONFIG="/etc/rclone/${SERVICE}.conf" +LOGDIR="/var/log/rclone/${SERVICE}" RCLONE="/usr/local/bin/rclone" timestamp="$(date +%Y%m%d%H%M%S)" +if [ ! -f "$CONFIG" ]; then + echo "ERR: Config file '${CONFIG}' does not exist" 1>&2 + exit 1 +fi if [ ! -d "$TARGET" ]; then echo "ERR: Destination directory '${TARGET}' does not exist" 1>&2 exit 1 @@ -27,3 +33,5 @@ for host in $("$RCLONE" --config "$CONFIG" listremotes | tr -d ":") ; do cat "$log" fi done + +find "$LOGDIR" -type f -name "*.log" -mtime +30 -delete diff --git a/roles/sftpbackup/meta/main.yml b/roles/rclone/meta/main.yml similarity index 100% rename from roles/sftpbackup/meta/main.yml rename to roles/rclone/meta/main.yml diff --git a/roles/rclone/tasks/main.yml b/roles/rclone/tasks/main.yml index fe8ba2e..455de9b 100644 --- a/roles/rclone/tasks/main.yml +++ b/roles/rclone/tasks/main.yml @@ -8,31 +8,78 @@ ansible.builtin.file: path: /etc/rclone state: directory - mode: 0755 + mode: "0755" owner: root group: "{{ ansible_wheel }}" - name: Create host config ansible.builtin.template: - dest: /etc/rclone/rclone.conf + dest: "/etc/rclone/{{ rclone_service }}.conf" src: rclone.conf.j2 - mode: 0644 + mode: "0640" + owner: root + group: "{{ rclone_service }}" + +- name: Create ssh keys + ansible.builtin.command: + argv: + - ssh-keygen + - -t + - ed25519 + - -C + - "{{ rclone_service }}@{{ inventory_hostname }}" + - -N + - "" + - -f + - "/etc/rclone/ssh_{{ rclone_service }}_ed25519_key" + creates: "/etc/rclone/ssh_{{ rclone_service }}_ed25519_key" + +- name: Fix ssh key permissions + ansible.builtin.file: + path: "{{ item }}" + owner: root + group: "{{ rclone_service }}" + mode: "0640" + with_items: + - "/etc/rclone/ssh_{{ rclone_service }}_ed25519_key" + - "/etc/rclone/ssh_{{ rclone_service }}_ed25519_key.pub" + +- name: Fetch ssh public key + ansible.builtin.fetch: + src: "/etc/rclone/ssh_{{ rclone_service }}_ed25519_key.pub" + dest: "../files/ssh/{{ rclone_service }}.pub" + flat: true + +- name: Create base log directory + ansible.builtin.file: + path: /var/log/rclone + state: directory + mode: "0755" owner: root group: "{{ ansible_wheel }}" - name: Create log directory ansible.builtin.file: - path: /var/log/rclone + path: "/var/log/rclone/{{ rclone_service }}" state: directory - mode: 0750 - owner: "{{ local_user | default('root') }}" - group: "{{ local_user | default(ansible_wheel) }}" + mode: "0750" + owner: "{{ rclone_service }}" + group: "{{ rclone_service }}" + +- name: Create data directories + ansible.builtin.file: + path: "/srv/{{ rclone_service }}/{{ item }}" + state: directory + mode: "0770" + owner: root + group: "{{ rclone_service }}" + with_items: "{{ groups[rclone_hostgroup | default(rclone_service)] }}" - name: Copy rclone sync script - ansible.builtin.template: + ansible.builtin.copy: dest: /usr/local/bin/rclone-sync - src: rclone-sync.sh.j2 - mode: 0755 + src: rclone-sync.sh + mode: "0755" owner: root group: "{{ ansible_wheel }}" @@ -40,16 +87,13 @@ ansible.builtin.cron: name: MAILTO env: true - user: "{{ local_user }}" + user: "{{ rclone_service }}" value: root - when: - - local_user is defined - - local_user != "root" - name: Add rclone sync cron job ansible.builtin.cron: name: rclone-sync - user: "{{ local_user | default('root') }}" + user: "{{ rclone_service }}" hour: "3" - minute: "{{ 60 | random(seed=inventory_hostname) }}" + minute: "00" job: /usr/local/bin/rclone-sync diff --git a/roles/rclone/templates/rclone.conf.j2 b/roles/rclone/templates/rclone.conf.j2 index 9389314..bc4f312 100644 --- a/roles/rclone/templates/rclone.conf.j2 +++ b/roles/rclone/templates/rclone.conf.j2 @@ -1,10 +1,11 @@ # {{ ansible_managed }} -{% for host in groups[hostgroup] %} +{% for host in groups[rclone_hostgroup | default(rclone_service)] %} [{{ host.split('.')[0] }}] type = sftp host = {{ host }} -user = {{ remote_user }} -key_file = {{ private_key | default('~/.ssh/id_ed25519') }} -known_hosts_file = /etc/ssh/ssh_known_hosts +user = {{ rclone_service }} +shell_type = none +key_file = /etc/rclone/ssh_{{ rclone_service }}_ed25519_key +known_hosts_file = /etc/ssh/ssh_known_hosts {% endfor %} diff --git a/roles/relayd/tasks/main.yml b/roles/relayd/tasks/main.yml index 35befda..1e82b13 100644 --- a/roles/relayd/tasks/main.yml +++ b/roles/relayd/tasks/main.yml @@ -3,7 +3,7 @@ ansible.builtin.template: dest: /etc/relayd.conf src: relayd.conf.j2 - mode: 0600 + mode: "0600" owner: root group: "{{ ansible_wheel }}" validate: "relayd -n -f %s" diff --git a/roles/reportmirror/defaults/main.yml b/roles/reportmirror/defaults/main.yml new file mode 100644 index 0000000..934a0e9 --- /dev/null +++ b/roles/reportmirror/defaults/main.yml @@ -0,0 +1,3 @@ +--- +reportmirror_hostname: "{{ inventory_hostname }}" +reportmirror_mirrors: [] diff --git a/roles/mirror/reportmirror/meta/main.yml b/roles/reportmirror/meta/main.yml similarity index 100% rename from roles/mirror/reportmirror/meta/main.yml rename to roles/reportmirror/meta/main.yml diff --git a/roles/mirror/reportmirror/tasks/main.yml b/roles/reportmirror/tasks/main.yml similarity index 92% rename from roles/mirror/reportmirror/tasks/main.yml rename to roles/reportmirror/tasks/main.yml index 193fa2e..487027d 100644 --- a/roles/mirror/reportmirror/tasks/main.yml +++ b/roles/reportmirror/tasks/main.yml @@ -8,13 +8,14 @@ ansible.builtin.git: dest: /usr/local/src/report_mirror repo: https://github.com/fedora-infra/mirrormanager2.git + update: true version: master - name: Install reportmirror script ansible.builtin.copy: dest: /usr/local/bin/report_mirror src: /usr/local/src/report_mirror/client/report_mirror - mode: 0755 + mode: "0755" owner: root group: "{{ ansible_wheel }}" remote_src: true @@ -23,7 +24,7 @@ ansible.builtin.file: dest: /etc/mirrormanager-client state: directory - mode: 0750 + mode: "0750" owner: root group: mirror @@ -31,6 +32,6 @@ ansible.builtin.template: dest: /etc/mirrormanager-client/report_mirror.conf src: report_mirror.conf.j2 - mode: 0640 + mode: "0640" owner: root group: mirror diff --git a/roles/mirror/reportmirror/templates/report_mirror.conf.j2 b/roles/reportmirror/templates/report_mirror.conf.j2 similarity index 91% rename from roles/mirror/reportmirror/templates/report_mirror.conf.j2 rename to roles/reportmirror/templates/report_mirror.conf.j2 index ae793f3..7181a22 100644 --- a/roles/mirror/reportmirror/templates/report_mirror.conf.j2 +++ b/roles/reportmirror/templates/report_mirror.conf.j2 @@ -11,8 +11,8 @@ enabled=1 # Name and Password fields need to match the Site name and password # fields you entered for your Site in the MirrorManager database at # https://admin.fedoraproject.org/mirrormanager -name={{ sitename }} -password={{ password }} +name={{ reportmirror_sitename }} +password={{ reportmirror_password }} [host] # if enabled=0, no data about this host is sent to the database @@ -20,7 +20,7 @@ enabled=1 # Name field need to match the Host name field you entered for your # Host in the MirrorManager database at # https://admin.fedoraproject.org/mirrormanager -name={{ hostname }} +name={{ reportmirror_hostname }} # if user_active=0, no data about this category is given to the public # This can be used to toggle between serving and not serving data, # such enabled during the nighttime (when you have more idle bandwidth @@ -52,15 +52,15 @@ rsyncd=/var/log/rsyncd.log # path= is the path on your local disk to the top-level directory for this Category [Fedora Linux] -{% if "fedora" in mirrors %} +{% if "fedora" in reportmirror_mirrors %} enabled=1 {% else %} enabled=0 {% endif %} path=/srv/mrirors/fedora -[Fedora EPEL] -{% if "epel" in mirrors %} +[Fedora EPELreport] +{% if "epel" in reportmirror_mirrors %} enabled=1 {% else %} enabled=0 diff --git a/roles/rocketchat/defaults/main.yml b/roles/rocketchat/defaults/main.yml new file mode 100644 index 0000000..6b40b0a --- /dev/null +++ b/roles/rocketchat/defaults/main.yml @@ -0,0 +1,2 @@ +--- +rocketchat_versin: default diff --git a/roles/rocketchat/handlers/main.yml b/roles/rocketchat/handlers/main.yml new file mode 100644 index 0000000..93b2616 --- /dev/null +++ b/roles/rocketchat/handlers/main.yml @@ -0,0 +1,6 @@ +--- +- name: Restart rocketchat + ansible.builtin.systemd: + name: rocketchat-container + daemon_reload: true + state: restarted diff --git a/roles/rocketchat/meta/main.yml b/roles/rocketchat/meta/main.yml new file mode 100644 index 0000000..700494e --- /dev/null +++ b/roles/rocketchat/meta/main.yml @@ -0,0 +1,3 @@ +--- +dependencies: + - {role: podman} diff --git a/roles/rocketchat/tasks/main.yml b/roles/rocketchat/tasks/main.yml new file mode 100644 index 0000000..da102d0 --- /dev/null +++ b/roles/rocketchat/tasks/main.yml @@ -0,0 +1,84 @@ +--- +- name: Create group + ansible.builtin.group: + name: rocketchat + +- name: Create user + ansible.builtin.user: + name: rocketchat + comment: Podman Rocket.Chat + group: rocketchat + shell: /sbin/nologin + +- name: Enable user lingering + ansible.builtin.command: + argv: + - loginctl + - enable-linger + - rocketchat + creates: /var/lib/systemd/linger/rocketchat + +- name: Generate combined certificate/private key file contents + ansible.builtin.command: + argv: + - /bin/cat + - "{{ tls_certs }}/{{ inventory_hostname }}.crt" + - "{{ tls_private }}/{{ inventory_hostname }}.key" + changed_when: false + check_mode: false + register: rocketchat_cert_key + +- name: Get rocketchat subgid value + ansible.builtin.command: + argv: + - sed + - -n + - 's/^rocketchat:\([0-9]\+\):[0-9]\+$/\1/p' + - /etc/subuid + changed_when: false + register: result + +- name: Create combined certificate/private key file + ansible.builtin.copy: + dest: "{{ tls_private }}/rocketchat.pem" + content: "{{ rocketchat_cert_key.stdout }}" + mode: "0640" + owner: root + group: "{{ result.stdout | int + 65532 }}" + notify: Restart rocketchat + +- name: Create service config + ansible.builtin.template: + dest: /etc/sysconfig/rocketchat-container + src: rocketchat-container.sysconfig.j2 + mode: "0600" + owner: root + group: "{{ ansible_wheel }}" + notify: Restart rocketchat + +- name: Create service file + ansible.builtin.template: + dest: /etc/systemd/system/rocketchat-container.service + src: rocketchat-container.service.j2 + mode: "0644" + owner: root + group: "{{ ansible_wheel }}" + notify: Restart rocketchat + +- name: Enable service + ansible.builtin.service: + name: rocketchat-container + state: started + enabled: true + +- name: Copy nginx config + ansible.builtin.copy: + dest: /etc/nginx/conf.d/{{ inventory_hostname }}/rocketchat-container.conf + content: | + location /rocketchat/ { + proxy_pass http://127.0.0.1:8008/; + } + mode: "0644" + owner: root + group: "{{ ansible_wheel }}" + notify: Restart nginx diff --git a/roles/rocketchat/templates/rocketchat-container.service.j2 b/roles/rocketchat/templates/rocketchat-container.service.j2 new file mode 100644 index 0000000..16f511a --- /dev/null +++ b/roles/rocketchat/templates/rocketchat-container.service.j2 @@ -0,0 +1,21 @@ +[Unit] +Description=Rocket.Chat Container +Wants=network-online.target +After=network-online.target + +[Service] +User=rocketchat +EnvironmentFile=/etc/sysconfig/rocketchat-container +ExecStartPre=/usr/bin/podman pull docker.io/rocketchat/rocket.chat:{{ rocketchat_version }} +ExecStart=/usr/bin/podman run \ + --rm -p 127.0.0.1:8008:3000 \ + --name rocketchat \ + --volume={{ tls_certs }}/ca.crt:/etc/ssl/certs/ca.crt:ro \ + --volume={{ tls_private }}/rocketchat.pem:/etc/ssl/private/rocketchat.pem:ro \ + --env ROOT_URL --env MONGO_URL --env MONGO_OPLOG_URL \ + docker.io/rocketchat/rocket.chat:{{ rocketchat_version }} +ExecStop=/usr/bin/podman stop --ignore rocketchat +ExecStopPost=/usr/bin/podman rm -f --ignore rocketchat + +[Install] +WantedBy=multi-user.target diff --git a/roles/rocketchat/templates/rocketchat-container.sysconfig.j2 b/roles/rocketchat/templates/rocketchat-container.sysconfig.j2 new file mode 100644 index 0000000..e023f32 --- /dev/null +++ b/roles/rocketchat/templates/rocketchat-container.sysconfig.j2 @@ -0,0 +1,3 @@ +ROOT_URL="https://chat.foo.sh/" +MONGO_URL="mongodb://rocketchat:{{ rocketchat_mongodb_pass }}@mongodb01.home.foo.sh:27017/rocketchat?tls=true&tlscafile=/etc/ssl/certs/ca.crt&tlscertificatekeyfile=/etc/ssl/private/rocketchat.pem" +MONGO_OPLOG_URL="mongodb://mongodb01.home.foo.sh:27017/local" diff --git a/roles/roles_lists/tasks/main.yml b/roles/roles_lists/tasks/main.yml index 5783bbf..049c0ef 100644 --- a/roles/roles_lists/tasks/main.yml +++ b/roles/roles_lists/tasks/main.yml @@ -3,7 +3,7 @@ ansible.builtin.copy: dest: /etc/smrsh/archiver src: archiver.sh - mode: 0755 + mode: "0755" owner: root group: "{{ ansible_wheel }}" @@ -20,7 +20,7 @@ ansible.builtin.copy: dest: /usr/local/share/selinux/sendmail-spamc.pp src: sendmail-spamc.pp - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" diff --git a/roles/roundcube/tasks/main.yml b/roles/roundcube/tasks/main.yml index a3f66ec..787a983 100644 --- a/roles/roundcube/tasks/main.yml +++ b/roles/roundcube/tasks/main.yml @@ -10,11 +10,19 @@ group: roundcube shell: /sbin/nologin +- name: Enable user lingering + ansible.builtin.command: + argv: + - loginctl + - enable-linger + - roundcube + creates: /var/lib/systemd/linger/roundcube + - name: Copy host key ansible.builtin.copy: dest: "{{ tls_private }}/roundcube.key" src: "{{ tls_private }}/{{ inventory_hostname }}.key" - mode: 0640 + mode: "0640" owner: root group: roundcube remote_src: true @@ -23,7 +31,7 @@ ansible.builtin.file: path: /etc/roundcube state: directory - mode: 0755 + mode: "0755" owner: root group: "{{ ansible_wheel }}" @@ -31,7 +39,7 @@ ansible.builtin.template: dest: /etc/roundcube/local.php src: local.php.j2 - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" @@ -39,7 +47,7 @@ ansible.builtin.template: dest: /etc/sysconfig/roundcube-container src: roundcube-container.sysconfig.j2 - mode: 0600 + mode: "0600" owner: root group: "{{ ansible_wheel }}" notify: Restart roundcube @@ -48,7 +56,7 @@ ansible.builtin.template: dest: /etc/systemd/system/roundcube-container.service src: roundcube-container.service.j2 - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" notify: Restart roundcube @@ -66,7 +74,7 @@ location /roundcube/ { proxy_pass http://localhost:8004/; } - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" notify: Restart nginx diff --git a/roles/roundcube/templates/local.php.j2 b/roles/roundcube/templates/local.php.j2 index 2935f09..ea54a4b 100644 --- a/roles/roundcube/templates/local.php.j2 +++ b/roles/roundcube/templates/local.php.j2 @@ -3,4 +3,11 @@ $config["domain"] = "{{ mail_domain }}"; $config["product_name"] = "foo.sh - Webmail"; +$config["plugins"] = array( + "database_attachments", +); + +$config['database_attachments_cache'] = 'db'; +$config['database_attachments_cache_ttl'] = 12 * 60 * 60; + ?> diff --git a/roles/routeros/files/README.md b/roles/routeros/files/README.md new file mode 100644 index 0000000..9e5cc1e --- /dev/null +++ b/roles/routeros/files/README.md @@ -0,0 +1,22 @@ +# Mikrotik Routeros Cheat Sheet + +## Update + +``` +/system package update print +/tool fetch url=https://oob.foo.sh/routeros/routeros-7.13.4-arm.npk +/system reboot +/system package update print +``` + +## Change port vlan + +``` +/interface/bridge/port/set [find where bridge=bridge and interface=ether1] pvid=30 +``` + +## Add name to port + +``` +/interface/ethernet/set [ find default-name=ether20 ] comment="name" +``` diff --git a/roles/routeros/files/download-routeros-firmware.sh b/roles/routeros/files/download-routeros-firmware.sh new file mode 100755 index 0000000..96260ca --- /dev/null +++ b/roles/routeros/files/download-routeros-firmware.sh @@ -0,0 +1,63 @@ +#!/bin/sh + +set -eu + +umask 022 + +cd /srv/web/oob.foo.sh/routeros + +verbose=false +if [ "${1:-}" = "-v" ]; then + verbose=true + shift +fi + +if [ $# -gt 0 ]; then + echo "Usage: $(basename "$0") [-v]" 1>&2 + exit 1 +fi + +packageinfo=$(curl -sSf "https://mikrotik.com/download" | awk -F '"' ' + { + if (!url && $0 ~ /routeros-[0-9\.]+-arm.npk/) { + url=$2 + } else if (!found && url && $0 ~ /data-checksum-sha256/) { + print url " " $6 + found = 1 + } + } + ') + +packageurl="$(echo "$packageinfo" | cut -d " " -f 1)" +checksum="$(echo "$packageinfo" | cut -d " " -f 2)" +if [ -z "$packageurl" ]; then + echo "ERR: Got empty package URL, exiting" 1>&2 + exit 1 +fi +packagename="$(basename "$packageurl")" +if [ -f "$packagename" ]; then + "$verbose" && echo "Already up to date" + exit 0 +fi + +if [ -z "$checksum" ]; then + echo "ERR: Failed to determine package checksum" 1>&2 + exit 1 +fi + +echo "Downloading new package '${packagename}'" +tmpfile="$(mktemp -p .)" +trap 'rm -f -- "$tmpfile"' EXIT +curl -sSf -o "$tmpfile" "$packageurl" + +if [ "$(sha256sum "$tmpfile" | cut -d " " -f 1)" != "$checksum" ]; then + echo "ERR: Checksum check failed, not saving package" 1>&2 + exit 1 +fi + +mv "$tmpfile" "$packagename" + +echo +curl -sSf "https://cdn.mikrotik.com/routeros/$(echo "$packagename" | cut -d "-" -f 2)/CHANGELOG" +echo +echo diff --git a/roles/routeros/files/mikrotik.mib b/roles/routeros/files/mikrotik.mib new file mode 100644 index 0000000..d640b4a --- /dev/null +++ b/roles/routeros/files/mikrotik.mib @@ -0,0 +1,4159 @@ +MIKROTIK-MIB DEFINITIONS ::= BEGIN + +IMPORTS +InetAddressType, InetAddress, InetPortNumber FROM INET-ADDRESS-MIB +MODULE-IDENTITY, OBJECT-TYPE, Integer32, Counter32, Gauge32, IpAddress, +Counter64, enterprises, NOTIFICATION-TYPE, TimeTicks FROM SNMPv2-SMI +TEXTUAL-CONVENTION, DisplayString, MacAddress, TruthValue, DateAndTime FROM SNMPv2-TC +OBJECT-GROUP, NOTIFICATION-GROUP FROM SNMPv2-CONF; + +mikrotikExperimentalModule MODULE-IDENTITY + LAST-UPDATED "202502050000Z" + ORGANIZATION "MikroTik" + CONTACT-INFO "support@mikrotik.com" + DESCRIPTION "" + REVISION "202502050000Z" + DESCRIPTION "" + ::= { mikrotik 1 } + +mikrotik OBJECT IDENTIFIER ::= { enterprises 14988 } +mtXMetaInfo OBJECT IDENTIFIER ::= { mikrotikExperimentalModule 2 } +mtXRouterOsGroups OBJECT IDENTIFIER ::= { mtXMetaInfo 1 } + +mtXRouterOs OBJECT IDENTIFIER ::= { mikrotikExperimentalModule 1 } +mtxrWireless OBJECT IDENTIFIER ::= { mtXRouterOs 1 } +mtxrQueues OBJECT IDENTIFIER ::= { mtXRouterOs 2 } +mtxrHealth OBJECT IDENTIFIER ::= { mtXRouterOs 3 } +mtxrLicense OBJECT IDENTIFIER ::= { mtXRouterOs 4 } +mtxrHotspot OBJECT IDENTIFIER ::= { mtXRouterOs 5 } +mtxrDHCP OBJECT IDENTIFIER ::= { mtXRouterOs 6 } +mtxrSystem OBJECT IDENTIFIER ::= { mtXRouterOs 7 } +mtxrScripts OBJECT IDENTIFIER ::= { mtXRouterOs 8 } +mtxrTraps OBJECT IDENTIFIER ::= { mtXRouterOs 9 } +mtxrNstremeDual OBJECT IDENTIFIER ::= { mtXRouterOs 10 } +mtxrNeighbor OBJECT IDENTIFIER ::= { mtXRouterOs 11 } +mtxrGps OBJECT IDENTIFIER ::= { mtXRouterOs 12 } +mtxrWirelessModem OBJECT IDENTIFIER ::= { mtXRouterOs 13 } +mtxrInterfaceStats OBJECT IDENTIFIER ::= { mtXRouterOs 14 } +mtxrPOE OBJECT IDENTIFIER ::= { mtXRouterOs 15 } +mtxrLTEModem OBJECT IDENTIFIER ::= { mtXRouterOs 16 } +mtxrPartition OBJECT IDENTIFIER ::= { mtXRouterOs 17 } +mtxrScriptRun OBJECT IDENTIFIER ::= { mtXRouterOs 18 } +mtxrOptical OBJECT IDENTIFIER ::= { mtXRouterOs 19 } +mtxrIPSec OBJECT IDENTIFIER ::= { mtXRouterOs 20 } +mtxrWifi OBJECT IDENTIFIER ::= { mtXRouterOs 21 } + +ObjectIndex ::= TEXTUAL-CONVENTION + DISPLAY-HINT "x" + STATUS current + DESCRIPTION "Internal " + SYNTAX Integer32 (0..2147483647) +-- Note that actually in RouterOs index values can be in range 0..4294967294, +-- this can sometimes make them negative. Any of the following syntaxes would +-- be more appropriate, but since Integer32 is used for InterfaceIndex in +-- IF-MIB, where it can also take negative values in RouterOs, it is used +-- here for consistency. +-- Also note that ObjectIndex value is not related to item numbers that are +-- used by console and shown by console print command. +-- +-- SYNTAX Integer32 (-2147483648..2147483647) +-- SYNTAX Unsigned32 (0..4294967295) + +HexInt ::= TEXTUAL-CONVENTION + DISPLAY-HINT "x" + STATUS current + DESCRIPTION "Hex" + SYNTAX Integer32 (-2147483648..2147483647) + +Voltage ::= TEXTUAL-CONVENTION + DISPLAY-HINT "d-1" + STATUS current + DESCRIPTION "" + SYNTAX Integer32 (-2147483648..2147483647) + +Temperature ::= TEXTUAL-CONVENTION + DISPLAY-HINT "d-1" + STATUS current + DESCRIPTION "" + SYNTAX Integer32 (-2147483648..2147483647) + +Power ::= TEXTUAL-CONVENTION + DISPLAY-HINT "d-1" + STATUS current + DESCRIPTION "" + SYNTAX Integer32 (-2147483648..2147483647) + +GDiv100 ::= TEXTUAL-CONVENTION + DISPLAY-HINT "d-2" + STATUS current + DESCRIPTION "/100" + SYNTAX Gauge32 + +GDiv1000 ::= TEXTUAL-CONVENTION + DISPLAY-HINT "d-3" + STATUS current + DESCRIPTION "/1000" + SYNTAX Gauge32 + +IDiv1000 ::= TEXTUAL-CONVENTION + DISPLAY-HINT "d-3" + STATUS current + DESCRIPTION "/1000" + SYNTAX Integer32 (-2147483648..2147483647) + +BoolValue ::= TEXTUAL-CONVENTION + STATUS current + DESCRIPTION + "Boolean value." + SYNTAX INTEGER { false(0), true(1) } + +IsakmpCookie ::= TEXTUAL-CONVENTION + DISPLAY-HINT "16a" + STATUS current + DESCRIPTION "ISAKMP cookie string" + SYNTAX OCTET STRING (SIZE (16)) + +-- WIRELESS ******************************************************************** + +mtxrWlStatTable OBJECT-TYPE + SYNTAX SEQUENCE OF MtxrWlStatEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "" + ::= { mtxrWireless 1 } + +mtxrWlStatEntry OBJECT-TYPE + SYNTAX MtxrWlStatEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "Wireless station mode interface" + INDEX { mtxrWlStatIndex } + ::= { mtxrWlStatTable 1 } + +MtxrWlStatEntry ::= SEQUENCE { + mtxrWlStatIndex ObjectIndex, + mtxrWlStatTxRate Gauge32, + mtxrWlStatRxRate Gauge32, + mtxrWlStatStrength Integer32, + mtxrWlStatSsid DisplayString, + mtxrWlStatBssid MacAddress, + mtxrWlStatFreq Integer32, + mtxrWlStatBand DisplayString, + mtxrWlStatTxCCQ Counter32, + mtxrWlStatRxCCQ Counter32 +} + +mtxrWlStatIndex OBJECT-TYPE + SYNTAX ObjectIndex + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "" + ::= { mtxrWlStatEntry 1 } + +mtxrWlStatTxRate OBJECT-TYPE + SYNTAX Gauge32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "bits per second" + ::= { mtxrWlStatEntry 2 } + +mtxrWlStatRxRate OBJECT-TYPE + SYNTAX Gauge32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "bits per second" + ::= { mtxrWlStatEntry 3 } + +mtxrWlStatStrength OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "dBm" + ::= { mtxrWlStatEntry 4 } + +mtxrWlStatSsid OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrWlStatEntry 5 } + +mtxrWlStatBssid OBJECT-TYPE + SYNTAX MacAddress + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrWlStatEntry 6 } + +mtxrWlStatFreq OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "megahertz" + ::= { mtxrWlStatEntry 7 } + +mtxrWlStatBand OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrWlStatEntry 8 } + +mtxrWlStatTxCCQ OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrWlStatEntry 9 } + +mtxrWlStatRxCCQ OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrWlStatEntry 10 } + +-- WlRtabTable +mtxrWlRtabTable OBJECT-TYPE + SYNTAX SEQUENCE OF MtxrWlRtabEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "" + ::= { mtxrWireless 2 } + +mtxrWlRtabEntry OBJECT-TYPE + SYNTAX MtxrWlRtabEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "Wireless registration table. It is indexed by remote + mac-address and local interface index" + INDEX { mtxrWlRtabAddr, mtxrWlRtabIface } + ::= { mtxrWlRtabTable 1 } + +MtxrWlRtabEntry ::= SEQUENCE { + mtxrWlRtabAddr MacAddress, + mtxrWlRtabIface ObjectIndex, + mtxrWlRtabStrength Integer32, + mtxrWlRtabTxBytes Counter32, + mtxrWlRtabRxBytes Counter32, + mtxrWlRtabTxPackets Counter32, + mtxrWlRtabRxPackets Counter32, + mtxrWlRtabTxRate Gauge32, + mtxrWlRtabRxRate Gauge32, + mtxrWlRtabRouterOSVersion DisplayString, + mtxrWlRtabUptime TimeTicks, + mtxrWlRtabSignalToNoise Integer32, + mtxrWlRtabTxStrengthCh0 Integer32, + mtxrWlRtabRxStrengthCh0 Integer32, + mtxrWlRtabTxStrengthCh1 Integer32, + mtxrWlRtabRxStrengthCh1 Integer32, + mtxrWlRtabTxStrengthCh2 Integer32, + mtxrWlRtabRxStrengthCh2 Integer32, + mtxrWlRtabTxStrength Integer32, + mtxrWlRtabRadioName DisplayString +} + +mtxrWlRtabAddr OBJECT-TYPE + SYNTAX MacAddress + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "" + ::= { mtxrWlRtabEntry 1 } + +mtxrWlRtabIface OBJECT-TYPE + SYNTAX ObjectIndex + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "" + ::= { mtxrWlRtabEntry 2 } + +mtxrWlRtabStrength OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "dBm" + ::= { mtxrWlRtabEntry 3 } + +mtxrWlRtabTxBytes OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrWlRtabEntry 4 } + +mtxrWlRtabRxBytes OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrWlRtabEntry 5 } + +mtxrWlRtabTxPackets OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrWlRtabEntry 6 } + +mtxrWlRtabRxPackets OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrWlRtabEntry 7 } + +mtxrWlRtabTxRate OBJECT-TYPE + SYNTAX Gauge32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "bits per second" + ::= { mtxrWlRtabEntry 8 } + +mtxrWlRtabRxRate OBJECT-TYPE + SYNTAX Gauge32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "bits per second" + ::= { mtxrWlRtabEntry 9 } + +mtxrWlRtabRouterOSVersion OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "RouterOS version" + ::= { mtxrWlRtabEntry 10 } + +mtxrWlRtabUptime OBJECT-TYPE + SYNTAX TimeTicks + MAX-ACCESS read-only + STATUS current + DESCRIPTION "uptime" + ::= { mtxrWlRtabEntry 11 } + +mtxrWlRtabSignalToNoise OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Measured in dB, if value does not exist it is indicated with 0" + ::= { mtxrWlRtabEntry 12 } + +mtxrWlRtabTxStrengthCh0 OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrWlRtabEntry 13 } + +mtxrWlRtabRxStrengthCh0 OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrWlRtabEntry 14 } + +mtxrWlRtabTxStrengthCh1 OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrWlRtabEntry 15 } + +mtxrWlRtabRxStrengthCh1 OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrWlRtabEntry 16 } + +mtxrWlRtabTxStrengthCh2 OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrWlRtabEntry 17 } + +mtxrWlRtabRxStrengthCh2 OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrWlRtabEntry 18 } + +mtxrWlRtabTxStrength OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrWlRtabEntry 19 } + +mtxrWlRtabRadioName OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrWlRtabEntry 20 } + +mtxrWlRtabEntryCount OBJECT-TYPE + SYNTAX Gauge32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Wireless registration table entry count" + ::= { mtxrWireless 4 } + +mtxrWlApTable OBJECT-TYPE + SYNTAX SEQUENCE OF MtxrWlApEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "" + ::= { mtxrWireless 3 } + +mtxrWlApEntry OBJECT-TYPE + SYNTAX MtxrWlApEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "Wireless access point mode interface" + INDEX { mtxrWlApIndex } + ::= { mtxrWlApTable 1 } + +MtxrWlApEntry ::= SEQUENCE { + mtxrWlApIndex ObjectIndex, + mtxrWlApTxRate Gauge32, + mtxrWlApRxRate Gauge32, + mtxrWlApSsid DisplayString, + mtxrWlApBssid MacAddress, + mtxrWlApClientCount Counter32, + mtxrWlApFreq Integer32, + mtxrWlApBand DisplayString, + mtxrWlApNoiseFloor Integer32, + mtxrWlApOverallTxCCQ Counter32, + mtxrWlApAuthClientCount Counter32 +} + +mtxrWlApIndex OBJECT-TYPE + SYNTAX ObjectIndex + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "" + ::= { mtxrWlApEntry 1 } + +mtxrWlApTxRate OBJECT-TYPE + SYNTAX Gauge32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "bits per second" + ::= { mtxrWlApEntry 2 } + +mtxrWlApRxRate OBJECT-TYPE + SYNTAX Gauge32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "bits per second" + ::= { mtxrWlApEntry 3 } + +mtxrWlApSsid OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrWlApEntry 4 } + +mtxrWlApBssid OBJECT-TYPE + SYNTAX MacAddress + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrWlApEntry 5 } + +mtxrWlApClientCount OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrWlApEntry 6 } + +mtxrWlApFreq OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "megahertz" + ::= { mtxrWlApEntry 7 } + +mtxrWlApBand OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrWlApEntry 8 } + +mtxrWlApNoiseFloor OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrWlApEntry 9 } + +mtxrWlApOverallTxCCQ OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrWlApEntry 10 } + +mtxrWlApAuthClientCount OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrWlApEntry 11 } + +mtxrWlCMRtabTable OBJECT-TYPE + SYNTAX SEQUENCE OF MtxrWlCMRtabEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "" + ::= { mtxrWireless 5 } + +mtxrWlCMRtabEntry OBJECT-TYPE + SYNTAX MtxrWlCMRtabEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "Wireless CAPSMAN registration table. It is indexed by remote + mac-address and local interface index" + INDEX { mtxrWlCMRtabAddr, mtxrWlCMRtabIface } + ::= { mtxrWlCMRtabTable 1 } + +MtxrWlCMRtabEntry ::= SEQUENCE { + mtxrWlCMRtabAddr MacAddress, + mtxrWlCMRtabIface ObjectIndex, + mtxrWlCMRtabUptime TimeTicks, + mtxrWlCMRtabTxBytes Counter32, + mtxrWlCMRtabRxBytes Counter32, + mtxrWlCMRtabTxPackets Counter32, + mtxrWlCMRtabRxPackets Counter32, + mtxrWlCMRtabTxRate Gauge32, + mtxrWlCMRtabRxRate Gauge32, + mtxrWlCMRtabTxStrength Integer32, + mtxrWlCMRtabRxStrength Integer32, + mtxrWlCMRtabSsid DisplayString, + mtxrWlCMRtabEapIdent DisplayString +} + +mtxrWlCMRtabAddr OBJECT-TYPE + SYNTAX MacAddress + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrWlCMRtabEntry 1 } + -- should not be accessible in SMIv2 + +mtxrWlCMRtabIface OBJECT-TYPE + SYNTAX ObjectIndex + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "" + ::= { mtxrWlCMRtabEntry 2 } + +mtxrWlCMRtabUptime OBJECT-TYPE + SYNTAX TimeTicks + MAX-ACCESS read-only + STATUS current + DESCRIPTION "uptime" + ::= { mtxrWlCMRtabEntry 3 } + +mtxrWlCMRtabTxBytes OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrWlCMRtabEntry 4 } + +mtxrWlCMRtabRxBytes OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrWlCMRtabEntry 5 } + +mtxrWlCMRtabTxPackets OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrWlCMRtabEntry 6 } + +mtxrWlCMRtabRxPackets OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrWlCMRtabEntry 7 } + +mtxrWlCMRtabTxRate OBJECT-TYPE + SYNTAX Gauge32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "bits per second" + ::= { mtxrWlCMRtabEntry 8 } + +mtxrWlCMRtabRxRate OBJECT-TYPE + SYNTAX Gauge32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "bits per second" + ::= { mtxrWlCMRtabEntry 9 } + +mtxrWlCMRtabTxStrength OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrWlCMRtabEntry 10 } + +mtxrWlCMRtabRxStrength OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrWlCMRtabEntry 11 } + +mtxrWlCMRtabSsid OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrWlCMRtabEntry 12 } + +mtxrWlCMRtabEapIdent OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrWlCMRtabEntry 13 } + +mtxrWlCMRtabEntryCount OBJECT-TYPE + SYNTAX Gauge32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Wireless CAPSMAN registration table entry count" + ::= { mtxrWireless 6 } + +mtxrWlCMREntryCount OBJECT-TYPE + SYNTAX Gauge32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Wireless CAPSMAN remote-cap entry count" + ::= { mtxrWireless 10 } + +mtxrWlCMTable OBJECT-TYPE + SYNTAX SEQUENCE OF MtxrWlCMEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "" + ::= { mtxrWireless 7 } + +mtxrWlCMEntry OBJECT-TYPE + SYNTAX MtxrWlCMEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "CAPS-MAN mode interface" + INDEX { mtxrWlCMIndex } + ::= { mtxrWlCMTable 1 } + +MtxrWlCMEntry ::= SEQUENCE { + mtxrWlCMIndex ObjectIndex, + mtxrWlCMRegClientCount Counter32, + mtxrWlCMAuthClientCount Counter32, + mtxrWlCMState DisplayString, + mtxrWlCMChannel DisplayString +} + +mtxrWlCMIndex OBJECT-TYPE + SYNTAX ObjectIndex + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "" + ::= { mtxrWlCMEntry 1 } + +mtxrWlCMRegClientCount OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrWlCMEntry 2 } + +mtxrWlCMAuthClientCount OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrWlCMEntry 3 } + +mtxrWlCMState OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrWlCMEntry 4 } + +mtxrWlCMChannel OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "for master only" + ::= { mtxrWlCMEntry 5 } + +-- +mtxrWlCMRemoteTable OBJECT-TYPE + SYNTAX SEQUENCE OF MtxrWlCMRemoteEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "" + ::= { mtxrWireless 11 } + +mtxrWlCMRemoteEntry OBJECT-TYPE + SYNTAX MtxrWlCMRemoteEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "CAPSMAN remote-cap list" + INDEX { mtxrWlCMRemoteIndex } + ::= { mtxrWlCMRemoteTable 1 } + +MtxrWlCMRemoteEntry ::= SEQUENCE { + mtxrWlCMRemoteIndex ObjectIndex, + mtxrWlCMRemoteName DisplayString, + mtxrWlCMRemoteState DisplayString, + mtxrWlCMRemoteAddress DisplayString, + mtxrWlCMRemoteRadios Counter32 +} + +mtxrWlCMRemoteIndex OBJECT-TYPE + SYNTAX ObjectIndex + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "" + ::= { mtxrWlCMRemoteEntry 1 } + +mtxrWlCMRemoteName OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrWlCMRemoteEntry 2 } + +mtxrWlCMRemoteState OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrWlCMRemoteEntry 3 } + +mtxrWlCMRemoteAddress OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrWlCMRemoteEntry 4 } + +mtxrWlCMRemoteRadios OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrWlCMRemoteEntry 5 } + +-- W60G +mtxrWl60GTable OBJECT-TYPE + SYNTAX SEQUENCE OF MtxrWl60GEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "" + ::= { mtxrWireless 8 } + +mtxrWl60GEntry OBJECT-TYPE + SYNTAX MtxrWl60GEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "W60G interface" + INDEX { mtxrWl60GIndex } + ::= { mtxrWl60GTable 1 } + +MtxrWl60GEntry ::= SEQUENCE { + mtxrWl60GIndex ObjectIndex, + mtxrWl60GMode INTEGER, + mtxrWl60GSsid DisplayString, + mtxrWl60GConnected BoolValue, + mtxrWl60GRemote MacAddress, + mtxrWl60GFreq Integer32, + mtxrWl60GMcs Integer32, + mtxrWl60GSignal Integer32, + mtxrWl60GTxSector Integer32, + mtxrWl60GTxSectorInfo DisplayString, + mtxrWl60GRssi Integer32, + mtxrWl60GPhyRate Gauge32 +} + +mtxrWl60GIndex OBJECT-TYPE + SYNTAX ObjectIndex + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "" + ::= { mtxrWl60GEntry 1 } + +mtxrWl60GMode OBJECT-TYPE + SYNTAX INTEGER { + apBridge(0), + stationBridge(1), + sniff(2), + bridge(3) + } + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrWl60GEntry 2 } + +mtxrWl60GSsid OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrWl60GEntry 3 } + +mtxrWl60GConnected OBJECT-TYPE + SYNTAX BoolValue + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrWl60GEntry 4 } + +mtxrWl60GRemote OBJECT-TYPE + SYNTAX MacAddress + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrWl60GEntry 5 } + +mtxrWl60GFreq OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Mhz" + ::= { mtxrWl60GEntry 6 } + +mtxrWl60GMcs OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrWl60GEntry 7 } + +mtxrWl60GSignal OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrWl60GEntry 8 } + +mtxrWl60GTxSector OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrWl60GEntry 9 } + +mtxrWl60GTxSectorInfo OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrWl60GEntry 11 } + +mtxrWl60GRssi OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrWl60GEntry 12 } + +mtxrWl60GPhyRate OBJECT-TYPE + SYNTAX Gauge32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrWl60GEntry 13 } + +-- W60GSta +mtxrWl60GStaTable OBJECT-TYPE + SYNTAX SEQUENCE OF MtxrWl60GStaEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "" + ::= { mtxrWireless 9 } + +mtxrWl60GStaEntry OBJECT-TYPE + SYNTAX MtxrWl60GStaEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "W60G stations" + INDEX { mtxrWl60GStaIndex } + ::= { mtxrWl60GStaTable 1 } + +MtxrWl60GStaEntry ::= SEQUENCE { + mtxrWl60GStaIndex ObjectIndex, + mtxrWl60GStaConnected BoolValue, + mtxrWl60GStaRemote MacAddress, + mtxrWl60GStaMcs Integer32, + mtxrWl60GStaSignal Integer32, + mtxrWl60GStaTxSector Integer32, + mtxrWl60GStaPhyRate Gauge32, + mtxrWl60GStaRssi Integer32, + mtxrWl60GStaDistance Integer32 +} + +mtxrWl60GStaIndex OBJECT-TYPE + SYNTAX ObjectIndex + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "" + ::= { mtxrWl60GStaEntry 1 } + +mtxrWl60GStaConnected OBJECT-TYPE + SYNTAX BoolValue + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrWl60GStaEntry 2 } + +mtxrWl60GStaRemote OBJECT-TYPE + SYNTAX MacAddress + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrWl60GStaEntry 3 } + +mtxrWl60GStaMcs OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrWl60GStaEntry 4 } + +mtxrWl60GStaSignal OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrWl60GStaEntry 5 } + +mtxrWl60GStaTxSector OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrWl60GStaEntry 6 } + +mtxrWl60GStaPhyRate OBJECT-TYPE + SYNTAX Gauge32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Mbits per second" + ::= { mtxrWl60GStaEntry 8 } + +mtxrWl60GStaRssi OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrWl60GStaEntry 9 } + +mtxrWl60GStaDistance OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "meters" + ::= { mtxrWl60GStaEntry 10 } + + +mtxrWirelessGroup OBJECT-GROUP OBJECTS { + mtxrWlStatTxRate, + mtxrWlStatRxRate, + mtxrWlStatStrength, + mtxrWlStatSsid, + mtxrWlStatBssid, + mtxrWlStatFreq, + mtxrWlStatBand, + mtxrWlStatTxCCQ, + mtxrWlStatRxCCQ, + mtxrWlRtabStrength, + mtxrWlRtabTxBytes, + mtxrWlRtabRxBytes, + mtxrWlRtabTxPackets, + mtxrWlRtabRxPackets, + mtxrWlRtabTxRate, + mtxrWlRtabRxRate, + mtxrWlRtabEntryCount, + mtxrWlRtabRouterOSVersion, + mtxrWlRtabUptime, + mtxrWlRtabSignalToNoise, + mtxrWlRtabTxStrengthCh0, + mtxrWlRtabRxStrengthCh0, + mtxrWlRtabTxStrengthCh1, + mtxrWlRtabRxStrengthCh1, + mtxrWlRtabTxStrengthCh2, + mtxrWlRtabRxStrengthCh2, + mtxrWlRtabTxStrength, + mtxrWlRtabRadioName, + mtxrWlApTxRate, + mtxrWlApRxRate, + mtxrWlApSsid, + mtxrWlApBssid, + mtxrWlApClientCount, + mtxrWlApBand, + mtxrWlApFreq, + mtxrWlApNoiseFloor, + mtxrWlApOverallTxCCQ, + mtxrWlApAuthClientCount, + mtxrWlCMRtabAddr, + mtxrWlCMRtabTxBytes, + mtxrWlCMRtabRxBytes, + mtxrWlCMRtabTxPackets, + mtxrWlCMRtabRxPackets, + mtxrWlCMRtabTxRate, + mtxrWlCMRtabRxRate, + mtxrWlCMRtabUptime, + mtxrWlCMRtabTxStrength, + mtxrWlCMRtabRxStrength, + mtxrWlCMRtabSsid, + mtxrWlCMRtabEntryCount, + mtxrWlCMREntryCount, + mtxrWlCMRegClientCount, + mtxrWlCMAuthClientCount, + mtxrWl60GMode, + mtxrWl60GSsid, + mtxrWl60GConnected, + mtxrWl60GRemote, + mtxrWl60GFreq, + mtxrWl60GMcs, + mtxrWl60GSignal, + mtxrWl60GTxSector, + mtxrWl60GTxSectorInfo, + mtxrWl60GRssi, + mtxrWl60GPhyRate, + mtxrWl60GStaConnected, + mtxrWl60GStaRemote, + mtxrWl60GStaMcs, + mtxrWl60GStaSignal, + mtxrWl60GStaTxSector + } + STATUS current + DESCRIPTION "" + ::= { mtXRouterOsGroups 1 } + +-- QUEUES ******************************************************************** + +mtxrQueueSimpleTable OBJECT-TYPE + SYNTAX SEQUENCE OF MtxrQueueSimpleEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "" + ::= { mtxrQueues 1 } + +mtxrQueueSimpleEntry OBJECT-TYPE + SYNTAX MtxrQueueSimpleEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "Simple queue" + INDEX { mtxrQueueSimpleIndex } + ::= { mtxrQueueSimpleTable 1 } + +MtxrQueueSimpleEntry ::= SEQUENCE { + mtxrQueueSimpleIndex ObjectIndex, + mtxrQueueSimpleName DisplayString, + mtxrQueueSimpleSrcAddr IpAddress, + mtxrQueueSimpleSrcMask IpAddress, + mtxrQueueSimpleDstAddr IpAddress, + mtxrQueueSimpleDstMask IpAddress, + mtxrQueueSimpleIface ObjectIndex, + mtxrQueueSimpleBytesIn Counter64, + mtxrQueueSimpleBytesOut Counter64, + mtxrQueueSimplePacketsIn Counter32, + mtxrQueueSimplePacketsOut Counter32, + mtxrQueueSimplePCQQueuesIn Counter32, + mtxrQueueSimplePCQQueuesOut Counter32, + mtxrQueueSimpleDroppedIn Counter32, + mtxrQueueSimpleDroppedOut Counter32 +} + +mtxrQueueSimpleIndex OBJECT-TYPE + SYNTAX ObjectIndex + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "" + ::= { mtxrQueueSimpleEntry 1 } + +mtxrQueueSimpleName OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrQueueSimpleEntry 2 } + +mtxrQueueSimpleSrcAddr OBJECT-TYPE + SYNTAX IpAddress + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrQueueSimpleEntry 3 } + +mtxrQueueSimpleSrcMask OBJECT-TYPE + SYNTAX IpAddress + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrQueueSimpleEntry 4 } + +mtxrQueueSimpleDstAddr OBJECT-TYPE + SYNTAX IpAddress + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrQueueSimpleEntry 5 } + +mtxrQueueSimpleDstMask OBJECT-TYPE + SYNTAX IpAddress + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrQueueSimpleEntry 6 } + +mtxrQueueSimpleIface OBJECT-TYPE + SYNTAX ObjectIndex + MAX-ACCESS read-only + STATUS current + DESCRIPTION "interface index" + ::= { mtxrQueueSimpleEntry 7 } + +mtxrQueueSimpleBytesIn OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrQueueSimpleEntry 8 } + +mtxrQueueSimpleBytesOut OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrQueueSimpleEntry 9 } + +mtxrQueueSimplePacketsIn OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrQueueSimpleEntry 10 } + +mtxrQueueSimplePacketsOut OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrQueueSimpleEntry 11 } + +mtxrQueueSimplePCQQueuesIn OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrQueueSimpleEntry 12 } + +mtxrQueueSimplePCQQueuesOut OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrQueueSimpleEntry 13 } + +mtxrQueueSimpleDroppedIn OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrQueueSimpleEntry 14 } + +mtxrQueueSimpleDroppedOut OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrQueueSimpleEntry 15 } + +mtxrQueueTreeTable OBJECT-TYPE + SYNTAX SEQUENCE OF MtxrQueueTreeEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "" + ::= { mtxrQueues 2 } + +mtxrQueueTreeEntry OBJECT-TYPE + SYNTAX MtxrQueueTreeEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "Tree queue" + INDEX { mtxrQueueTreeIndex } + ::= { mtxrQueueTreeTable 1 } + +MtxrQueueTreeEntry ::= SEQUENCE { + mtxrQueueTreeIndex ObjectIndex, + mtxrQueueTreeName DisplayString, + mtxrQueueTreeFlow DisplayString, + mtxrQueueTreeParentIndex ObjectIndex, + mtxrQueueTreeBytes Counter32, + mtxrQueueTreePackets Counter32, + mtxrQueueTreeHCBytes Counter64, + mtxrQueueTreePCQQueues Counter32, + mtxrQueueTreeDropped Counter32 +} + +mtxrQueueTreeIndex OBJECT-TYPE + SYNTAX ObjectIndex + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "" + ::= { mtxrQueueTreeEntry 1 } + +mtxrQueueTreeName OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrQueueTreeEntry 2 } + +mtxrQueueTreeFlow OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "flowmark" + ::= { mtxrQueueTreeEntry 3 } + +mtxrQueueTreeParentIndex OBJECT-TYPE + SYNTAX ObjectIndex + MAX-ACCESS read-only + STATUS current + DESCRIPTION "index of parent tree queue or parent interface" + ::= { mtxrQueueTreeEntry 4 } + +mtxrQueueTreeBytes OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrQueueTreeEntry 5 } + +mtxrQueueTreePackets OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrQueueTreeEntry 6 } + +mtxrQueueTreeHCBytes OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrQueueTreeEntry 7 } + +mtxrQueueTreePCQQueues OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrQueueTreeEntry 8 } + +mtxrQueueTreeDropped OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrQueueTreeEntry 9 } + +mtxrQueueGroup OBJECT-GROUP OBJECTS { + mtxrQueueSimpleName, mtxrQueueSimpleSrcAddr, mtxrQueueSimpleSrcMask, + mtxrQueueSimpleDstAddr, mtxrQueueSimpleDstMask, mtxrQueueSimpleIface, + mtxrQueueSimpleBytesIn, mtxrQueueSimpleBytesOut, + mtxrQueueSimplePacketsIn, mtxrQueueSimplePacketsOut, mtxrQueueTreeName, + mtxrQueueSimplePCQQueuesIn, + mtxrQueueSimplePCQQueuesOut, + mtxrQueueSimpleDroppedIn, + mtxrQueueSimpleDroppedOut, + mtxrQueueTreeFlow, mtxrQueueTreeParentIndex, mtxrQueueTreeBytes, + mtxrQueueTreePackets, + mtxrQueueTreeHCBytes, + mtxrQueueTreePCQQueues, + mtxrQueueTreeDropped + } + STATUS current + DESCRIPTION "" + ::= { mtXRouterOsGroups 2 } + +-- HEALTH ******************************************************************** + +mtxrHlCoreVoltage OBJECT-TYPE + SYNTAX Voltage + MAX-ACCESS read-only + STATUS current + DESCRIPTION "core voltage" + ::= { mtxrHealth 1 } + +mtxrHlThreeDotThreeVoltage OBJECT-TYPE + SYNTAX Voltage + MAX-ACCESS read-only + STATUS current + DESCRIPTION "3.3V voltage" + ::= { mtxrHealth 2 } + +mtxrHlFiveVoltage OBJECT-TYPE + SYNTAX Voltage + MAX-ACCESS read-only + STATUS current + DESCRIPTION "5V voltage" + ::= { mtxrHealth 3 } + +mtxrHlTwelveVoltage OBJECT-TYPE + SYNTAX Voltage + MAX-ACCESS read-only + STATUS current + DESCRIPTION "12V voltage" + ::= { mtxrHealth 4 } + +mtxrHlSensorTemperature OBJECT-TYPE + SYNTAX Temperature + MAX-ACCESS read-only + STATUS current + DESCRIPTION "temperature at sensor chip" + ::= { mtxrHealth 5 } + +mtxrHlCpuTemperature OBJECT-TYPE + SYNTAX Temperature + MAX-ACCESS read-only + STATUS current + DESCRIPTION "temperature near cpu" + ::= { mtxrHealth 6 } + +mtxrHlBoardTemperature OBJECT-TYPE + SYNTAX Temperature + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrHealth 7 } + +mtxrHlVoltage OBJECT-TYPE + SYNTAX Voltage + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrHealth 8 } + +mtxrHlActiveFan OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrHealth 9 } + +mtxrHlTemperature OBJECT-TYPE + SYNTAX Temperature + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrHealth 10 } + +mtxrHlProcessorTemperature OBJECT-TYPE + SYNTAX Temperature + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrHealth 11 } + +mtxrHlPower OBJECT-TYPE + SYNTAX Power + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Watts" + ::= { mtxrHealth 12 } + +mtxrHlCurrent OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "mA" + ::= { mtxrHealth 13 } + +mtxrHlProcessorFrequency OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Mhz" + ::= { mtxrHealth 14 } + +mtxrHlPowerSupplyState OBJECT-TYPE + SYNTAX BoolValue + MAX-ACCESS read-only + STATUS current + DESCRIPTION "PSU state ok" + ::= { mtxrHealth 15 } + +mtxrHlBackupPowerSupplyState OBJECT-TYPE + SYNTAX BoolValue + MAX-ACCESS read-only + STATUS current + DESCRIPTION "backup PSU state ok" + ::= { mtxrHealth 16 } + +mtxrHlFanSpeed1 OBJECT-TYPE + SYNTAX Gauge32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "rpm" + ::= { mtxrHealth 17 } + +mtxrHlFanSpeed2 OBJECT-TYPE + SYNTAX Gauge32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "rpm" + ::= { mtxrHealth 18 } + +mtxrAlarmSocketStatus OBJECT-TYPE + SYNTAX INTEGER { + inactive(0), + active(1) + } + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Alarm socket status" + ::= { mtxrHealth 19 } + +mtxrGaugeTable OBJECT-TYPE + SYNTAX SEQUENCE OF MtxrGaugeTableEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "" + ::= { mtxrHealth 100 } + +mtxrGaugeTableEntry OBJECT-TYPE + SYNTAX MtxrGaugeTableEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "" + INDEX { mtxrGaugeIndex } + ::= { mtxrGaugeTable 1 } + +MtxrGaugeTableEntry ::= SEQUENCE { + mtxrGaugeIndex ObjectIndex, + mtxrGaugeName DisplayString, + mtxrGaugeValue Integer32, + mtxrGaugeUnit INTEGER +} + +mtxrGaugeIndex OBJECT-TYPE + SYNTAX ObjectIndex + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "" + ::= { mtxrGaugeTableEntry 1 } + +mtxrGaugeName OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrGaugeTableEntry 2 } + +mtxrGaugeValue OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrGaugeTableEntry 3 } + +mtxrGaugeUnit OBJECT-TYPE + SYNTAX INTEGER { + celsius(1), + rpm(2), + dV(3), + dA(4), + dW(5), + status(6) + } + MAX-ACCESS read-only + STATUS current + DESCRIPTION "units" + ::= { mtxrGaugeTableEntry 4 } + +mtxrHealthGroup OBJECT-GROUP OBJECTS { + mtxrHlCoreVoltage, mtxrHlThreeDotThreeVoltage, mtxrHlFiveVoltage, + mtxrHlTwelveVoltage, mtxrHlSensorTemperature, mtxrHlCpuTemperature, + mtxrHlBoardTemperature, mtxrHlVoltage, mtxrHlActiveFan, + mtxrHlTemperature, mtxrHlProcessorTemperature, + mtxrHlCurrent, mtxrHlPower, + mtxrHlProcessorFrequency, + mtxrHlPowerSupplyState, mtxrHlBackupPowerSupplyState, + mtxrHlFanSpeed1, mtxrHlFanSpeed2, mtxrAlarmSocketStatus, + mtxrGaugeName, mtxrGaugeValue, mtxrGaugeUnit + } + STATUS current + DESCRIPTION "" + ::= { mtXRouterOsGroups 3 } + +-- LICENSE ******************************************************************** + +mtxrLicSoftwareId OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "software id" + ::= { mtxrLicense 1 } + +mtxrLicUpgrUntil OBJECT-TYPE + SYNTAX DateAndTime + MAX-ACCESS read-only + STATUS current + DESCRIPTION "current key allows upgrading until this date" + ::= { mtxrLicense 2 } + +mtxrLicLevel OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "current key level" + ::= { mtxrLicense 3 } + +mtxrLicVersion OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "software version" + ::= { mtxrLicense 4 } + +mtxrLicUpgradableTo OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "upgradable to" + ::= { mtxrLicense 5 } + +mtxrLincenseGroup OBJECT-GROUP OBJECTS { + mtxrLicSoftwareId, mtxrLicUpgrUntil, mtxrLicLevel, mtxrLicVersion, mtxrLicUpgradableTo + } + STATUS current + DESCRIPTION "" + ::= { mtXRouterOsGroups 4 } + +-- HOTSPOT *************************************************************** + +mtxrHotspotActiveUsersTable OBJECT-TYPE + SYNTAX SEQUENCE OF MtxrHotspotActiveUsersTableEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "" + ::= { mtxrHotspot 1 } + +mtxrHotspotActiveUsersTableEntry OBJECT-TYPE + SYNTAX MtxrHotspotActiveUsersTableEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "" + INDEX { mtxrHotspotActiveUserIndex } + ::= { mtxrHotspotActiveUsersTable 1 } + +MtxrHotspotActiveUsersTableEntry ::= SEQUENCE { + mtxrHotspotActiveUserIndex ObjectIndex, + mtxrHotspotActiveUserServerID Integer32, + mtxrHotspotActiveUserName DisplayString, + mtxrHotspotActiveUserDomain DisplayString, + mtxrHotspotActiveUserIP IpAddress, + mtxrHotspotActiveUserMAC MacAddress, + mtxrHotspotActiveUserConnectTime Integer32, + mtxrHotspotActiveUserValidTillTime Integer32, + mtxrHotspotActiveUserIdleStartTime Integer32, + mtxrHotspotActiveUserIdleTimeout Integer32, + mtxrHotspotActiveUserPingTimeout Integer32, + mtxrHotspotActiveUserBytesIn Counter64, + mtxrHotspotActiveUserBytesOut Counter64, + mtxrHotspotActiveUserPacketsIn Counter64, + mtxrHotspotActiveUserPacketsOut Counter64, + mtxrHotspotActiveUserLimitBytesIn Counter64, + mtxrHotspotActiveUserLimitBytesOut Counter64, + mtxrHotspotActiveUserAdvertStatus Integer32, + mtxrHotspotActiveUserRadius Integer32, + mtxrHotspotActiveUserBlockedByAdvert Integer32 +} + +mtxrHotspotActiveUserIndex OBJECT-TYPE + SYNTAX ObjectIndex + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "" + ::= { mtxrHotspotActiveUsersTableEntry 1 } + +mtxrHotspotActiveUserServerID OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrHotspotActiveUsersTableEntry 2 } + +mtxrHotspotActiveUserName OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrHotspotActiveUsersTableEntry 3 } + +mtxrHotspotActiveUserDomain OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrHotspotActiveUsersTableEntry 4 } + +mtxrHotspotActiveUserIP OBJECT-TYPE + SYNTAX IpAddress + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrHotspotActiveUsersTableEntry 5 } + +mtxrHotspotActiveUserMAC OBJECT-TYPE + SYNTAX MacAddress + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrHotspotActiveUsersTableEntry 6 } + +mtxrHotspotActiveUserConnectTime OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrHotspotActiveUsersTableEntry 7 } + +mtxrHotspotActiveUserValidTillTime OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrHotspotActiveUsersTableEntry 8 } + +mtxrHotspotActiveUserIdleStartTime OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrHotspotActiveUsersTableEntry 9 } + +mtxrHotspotActiveUserIdleTimeout OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrHotspotActiveUsersTableEntry 10 } + +mtxrHotspotActiveUserPingTimeout OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrHotspotActiveUsersTableEntry 11 } + +mtxrHotspotActiveUserBytesIn OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrHotspotActiveUsersTableEntry 12 } + +mtxrHotspotActiveUserBytesOut OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrHotspotActiveUsersTableEntry 13 } + +mtxrHotspotActiveUserPacketsIn OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrHotspotActiveUsersTableEntry 14 } + +mtxrHotspotActiveUserPacketsOut OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrHotspotActiveUsersTableEntry 15 } + +mtxrHotspotActiveUserLimitBytesIn OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrHotspotActiveUsersTableEntry 16 } + +mtxrHotspotActiveUserLimitBytesOut OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrHotspotActiveUsersTableEntry 17 } + +mtxrHotspotActiveUserAdvertStatus OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrHotspotActiveUsersTableEntry 18 } + +mtxrHotspotActiveUserRadius OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrHotspotActiveUsersTableEntry 19 } + +mtxrHotspotActiveUserBlockedByAdvert OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrHotspotActiveUsersTableEntry 20 } + +mtxrHotspotActiveUserGroup OBJECT-GROUP OBJECTS { + mtxrHotspotActiveUserServerID, + mtxrHotspotActiveUserName, + mtxrHotspotActiveUserDomain, + mtxrHotspotActiveUserIP, + mtxrHotspotActiveUserMAC, + mtxrHotspotActiveUserConnectTime, + mtxrHotspotActiveUserValidTillTime, + mtxrHotspotActiveUserIdleStartTime, + mtxrHotspotActiveUserIdleTimeout, + mtxrHotspotActiveUserPingTimeout, + mtxrHotspotActiveUserBytesIn, + mtxrHotspotActiveUserBytesOut, + mtxrHotspotActiveUserPacketsIn, + mtxrHotspotActiveUserPacketsOut, + mtxrHotspotActiveUserLimitBytesIn, + mtxrHotspotActiveUserLimitBytesOut, + mtxrHotspotActiveUserAdvertStatus, + mtxrHotspotActiveUserRadius, + mtxrHotspotActiveUserBlockedByAdvert + } + STATUS current + DESCRIPTION "" + ::= { mtXRouterOsGroups 5 } + +-- DHCP ******************************************************************** + +mtxrDHCPLeaseCount OBJECT-TYPE + SYNTAX Gauge32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrDHCP 1 } + +mtxrDHCPGroup OBJECT-GROUP OBJECTS { + mtxrDHCPLeaseCount + } + STATUS current + DESCRIPTION "" + ::= { mtXRouterOsGroups 12 } + +-- SYSTEM ******************************************************************** + +mtxrSystemReboot OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-write + STATUS current + DESCRIPTION "set non zero to reboot" + ::= { mtxrSystem 1 } + +mtxrUSBPowerReset OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-write + STATUS current + DESCRIPTION "switches off usb power for specified amout of seconds" + ::= { mtxrSystem 2 } + +mtxrSerialNumber OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "RouterBOARD serial number" + ::= { mtxrSystem 3 } + +mtxrFirmwareVersion OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Current firmware version" + ::= { mtxrSystem 4 } + +mtxrNote OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "note" + ::= { mtxrSystem 5 } + +mtxrBuildTime OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "build time" + ::= { mtxrSystem 6 } + +mtxrFirmwareUpgradeVersion OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Upgrade firmware version" + ::= { mtxrSystem 7 } + +mtxrDisplayName OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "display name" + ::= { mtxrSystem 8 } + +mtxrBoardName OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "board name" + ::= { mtxrSystem 9 } + +mtxrSystemGroup OBJECT-GROUP OBJECTS { + mtxrSystemReboot, + mtxrUSBPowerReset, + mtxrSerialNumber, + mtxrFirmwareVersion, + mtxrNote, + mtxrBuildTime, + mtxrFirmwareUpgradeVersion, + mtxrBoardName + } + STATUS current + DESCRIPTION "" + ::= { mtXRouterOsGroups 13 } + +-- SCRIPTS ******************************************************************** + +mtxrScriptTable OBJECT-TYPE + SYNTAX SEQUENCE OF MtxrScriptTableEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "" + ::= { mtxrScripts 1 } + +mtxrScriptTableEntry OBJECT-TYPE + SYNTAX MtxrScriptTableEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "" + INDEX { mtxrScriptIndex } + ::= { mtxrScriptTable 1 } + +MtxrScriptTableEntry ::= SEQUENCE { + mtxrScriptIndex ObjectIndex, + mtxrScriptName DisplayString, + mtxrScriptRunCmd Integer32 +} + +mtxrScriptIndex OBJECT-TYPE + SYNTAX ObjectIndex + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "" + ::= { mtxrScriptTableEntry 1 } + +mtxrScriptName OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrScriptTableEntry 2 } + +mtxrScriptRunCmd OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-write + STATUS current + DESCRIPTION "set non zero to run" + ::= { mtxrScriptTableEntry 3 } + +mtxrScriptGroup OBJECT-GROUP OBJECTS { + mtxrScriptName, mtxrScriptRunCmd + } + STATUS current + DESCRIPTION "" + ::= { mtXRouterOsGroups 8 } + +-- SCRIPT RUN ***************************************************************** + +mtxrScriptRunTable OBJECT-TYPE + SYNTAX SEQUENCE OF MtxrScriptRunTableEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "invisible to getnext, accesible only with get request and write premission" + ::= { mtxrScriptRun 1 } + +mtxrScriptRunTableEntry OBJECT-TYPE + SYNTAX MtxrScriptRunTableEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "" + INDEX { mtxrScriptRunIndex } + ::= { mtxrScriptRunTable 1 } + +MtxrScriptRunTableEntry ::= SEQUENCE { + mtxrScriptRunIndex ObjectIndex, + mtxrScriptRunOutput DisplayString +} + +mtxrScriptRunIndex OBJECT-TYPE + SYNTAX ObjectIndex + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "" + ::= { mtxrScriptRunTableEntry 1 } + +mtxrScriptRunOutput OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "this oid on get request will run script and return it's output" + ::= { mtxrScriptRunTableEntry 2 } + +mtxrScriptRunGroup OBJECT-GROUP OBJECTS { + mtxrScriptRunOutput + } + STATUS current + DESCRIPTION "" + ::= { mtXRouterOsGroups 21 } + +-- Dual Nstreme *************************************************************** + +mtxrDnStatTable OBJECT-TYPE + SYNTAX SEQUENCE OF MtxrDnStatEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "" + ::= { mtxrNstremeDual 1 } + +mtxrDnStatEntry OBJECT-TYPE + SYNTAX MtxrDnStatEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "Nstreme Dual interface" + INDEX { mtxrDnStatIndex } + ::= { mtxrDnStatTable 1 } + +MtxrDnStatEntry ::= SEQUENCE { + mtxrDnStatIndex ObjectIndex, + mtxrDnStatTxRate Gauge32, + mtxrDnStatRxRate Gauge32, + mtxrDnStatTxStrength Integer32, + mtxrDnStatRxStrength Integer32, + mtxrDnConnected Integer32 +} + +mtxrDnStatIndex OBJECT-TYPE + SYNTAX ObjectIndex + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "" + ::= { mtxrDnStatEntry 1 } + +mtxrDnStatTxRate OBJECT-TYPE + SYNTAX Gauge32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "bits per second" + ::= { mtxrDnStatEntry 2 } + +mtxrDnStatRxRate OBJECT-TYPE + SYNTAX Gauge32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "bits per second" + ::= { mtxrDnStatEntry 3 } + +mtxrDnStatTxStrength OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "dBm" + ::= { mtxrDnStatEntry 4 } + +mtxrDnStatRxStrength OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "dBm" + ::= { mtxrDnStatEntry 5 } + +mtxrDnConnected OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "0 - not connected, connected otherwise" + ::= { mtxrDnStatEntry 6 } + +mtxrNstremeDualGroup OBJECT-GROUP OBJECTS { + mtxrDnStatTxRate, mtxrDnStatRxRate, + mtxrDnStatTxStrength, mtxrDnStatRxStrength, mtxrDnConnected + } + STATUS current + DESCRIPTION "" + ::= { mtXRouterOsGroups 10 } + +-- NEIGHBOR ******************************************************************* + +mtxrNeighborTable OBJECT-TYPE + SYNTAX SEQUENCE OF MtxrNeighborTableEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "" + ::= { mtxrNeighbor 1 } + +mtxrNeighborTableEntry OBJECT-TYPE + SYNTAX MtxrNeighborTableEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "" + INDEX { mtxrNeighborIndex } + ::= { mtxrNeighborTable 1 } + +MtxrNeighborTableEntry ::= SEQUENCE { + mtxrNeighborIndex ObjectIndex, + mtxrNeighborIpAddress IpAddress, + mtxrNeighborMacAddress MacAddress, + mtxrNeighborVersion DisplayString, + mtxrNeighborPlatform DisplayString, + mtxrNeighborIdentity DisplayString, + mtxrNeighborSoftwareID DisplayString, + mtxrNeighborInterfaceID ObjectIndex +} + +mtxrNeighborIndex OBJECT-TYPE + SYNTAX ObjectIndex + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "" + ::= { mtxrNeighborTableEntry 1 } + +mtxrNeighborIpAddress OBJECT-TYPE + SYNTAX IpAddress + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrNeighborTableEntry 2 } + +mtxrNeighborMacAddress OBJECT-TYPE + SYNTAX MacAddress + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrNeighborTableEntry 3 } + +mtxrNeighborVersion OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrNeighborTableEntry 4 } + +mtxrNeighborPlatform OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrNeighborTableEntry 5 } + +mtxrNeighborIdentity OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrNeighborTableEntry 6 } + +mtxrNeighborSoftwareID OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrNeighborTableEntry 7 } + +mtxrNeighborInterfaceID OBJECT-TYPE + SYNTAX ObjectIndex + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrNeighborTableEntry 8 } + +mtxrNeighborGroup OBJECT-GROUP OBJECTS { + mtxrNeighborIpAddress, + mtxrNeighborMacAddress, + mtxrNeighborVersion, + mtxrNeighborPlatform, + mtxrNeighborIdentity, + mtxrNeighborSoftwareID, + mtxrNeighborInterfaceID + } + STATUS current + DESCRIPTION "" + ::= { mtXRouterOsGroups 11 } + +-- GPS ************************************************************************ + +mtxrDate OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "UNIX time" + ::= { mtxrGps 1 } + +mtxrLongtitude OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "longtitude" + ::= { mtxrGps 2 } + +mtxrLatitude OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "latitude" + ::= { mtxrGps 3 } + +mtxrAltitude OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "altitude" + ::= { mtxrGps 4 } + +mtxrSpeed OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "speed" + ::= { mtxrGps 5 } + +mtxrSattelites OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "visible sattelite count" + ::= { mtxrGps 6 } + +mtxrValid OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "is the data valid" + ::= { mtxrGps 7 } + +mtxrGPSGroup OBJECT-GROUP OBJECTS { + mtxrDate, + mtxrLongtitude, + mtxrLatitude, + mtxrAltitude, + mtxrSpeed, + mtxrSattelites, + mtxrValid + } + STATUS current + DESCRIPTION "" + ::= { mtXRouterOsGroups 15 } + +-- Wireless Modem ************************************************************ + +mtxrWirelessModemSignalStrength OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "signal strength in dBm (if first ppp-client modem supports)" + ::= { mtxrWirelessModem 1 } + +mtxrWirelessModemSignalECIO OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "signal EC/IO in dB (if first ppp-client modem supports)" + ::= { mtxrWirelessModem 2 } + +mtxrWirelessModemManufacturer OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Modem manufacturer name" + ::= { mtxrWirelessModem 3 } + +mtxrWirelessModemModel OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Modem model name" + ::= { mtxrWirelessModem 4 } + +mtxrWirelessModemRevision OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Modem firmware revision" + ::= { mtxrWirelessModem 5 } + +mtxrWirelessModemIMEI OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Modem serial number" + ::= { mtxrWirelessModem 6 } + +mtxrWirelessModemIMSI OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "International mobile subscriber identity" + ::= { mtxrWirelessModem 7 } + +mtxrWirelessModemAccessTechnology OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Access technology" + ::= { mtxrWirelessModem 8 } + +mtxrWirelessModemFrameErrorRate OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Signal frame error rate" + ::= { mtxrWirelessModem 9 } + +mtxrWirelessModemRSRP OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Reference Signal Receive Power" + ::= { mtxrWirelessModem 10 } + +mtxrWirelessModemRSRQ OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Reference Signal Received Quality" + ::= { mtxrWirelessModem 11 } + +mtxrWirelessModemSINR OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Signal-to-Interference-plus-Noise Ratio" + ::= { mtxrWirelessModem 12 } + +mtxrWirelessModemGroup OBJECT-GROUP OBJECTS { + mtxrWirelessModemSignalStrength, + mtxrWirelessModemSignalECIO, + mtxrWirelessModemManufacturer, + mtxrWirelessModemModel, + mtxrWirelessModemRevision, + mtxrWirelessModemIMEI, + mtxrWirelessModemIMSI, + mtxrWirelessModemAccessTechnology, + mtxrWirelessModemFrameErrorRate, + mtxrWirelessModemRSRP, + mtxrWirelessModemRSRQ, + mtxrWirelessModemSINR + } + STATUS current + DESCRIPTION "" + ::= { mtXRouterOsGroups 16 } + +-- Interface Stats ************************************************************ + +mtxrInterfaceStatsTable OBJECT-TYPE + SYNTAX SEQUENCE OF MtxrInterfaceStatsEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "Extended interface statistics. + Some interfaces may have only parts of this table + with unavailable values set to zero." + ::= { mtxrInterfaceStats 1 } + +mtxrInterfaceStatsEntry OBJECT-TYPE + SYNTAX MtxrInterfaceStatsEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "" + INDEX { mtxrInterfaceStatsIndex } + ::= { mtxrInterfaceStatsTable 1 } + +MtxrInterfaceStatsEntry ::= SEQUENCE { + mtxrInterfaceStatsIndex ObjectIndex, + mtxrInterfaceStatsName DisplayString, + + mtxrInterfaceStatsDriverRxBytes Counter64, + mtxrInterfaceStatsDriverRxPackets Counter64, + mtxrInterfaceStatsDriverTxBytes Counter64, + mtxrInterfaceStatsDriverTxPackets Counter64, + + mtxrInterfaceStatsTxRx64 Counter64, + mtxrInterfaceStatsTxRx65To127 Counter64, + mtxrInterfaceStatsTxRx128To255 Counter64, + mtxrInterfaceStatsTxRx256To511 Counter64, + mtxrInterfaceStatsTxRx512To1023 Counter64, + mtxrInterfaceStatsTxRx1024To1518 Counter64, + mtxrInterfaceStatsTxRx1519ToMax Counter64, + + mtxrInterfaceStatsRxBytes Counter64, + mtxrInterfaceStatsRxPackets Counter64, + mtxrInterfaceStatsRxTooShort Counter64, + mtxrInterfaceStatsRx64 Counter64, + mtxrInterfaceStatsRx65To127 Counter64, + mtxrInterfaceStatsRx128To255 Counter64, + mtxrInterfaceStatsRx256To511 Counter64, + mtxrInterfaceStatsRx512To1023 Counter64, + mtxrInterfaceStatsRx1024To1518 Counter64, + mtxrInterfaceStatsRx1519ToMax Counter64, + mtxrInterfaceStatsRxTooLong Counter64, + mtxrInterfaceStatsRxBroadcast Counter64, + mtxrInterfaceStatsRxPause Counter64, + mtxrInterfaceStatsRxMulticast Counter64, + mtxrInterfaceStatsRxFCSError Counter64, + mtxrInterfaceStatsRxAlignError Counter64, + mtxrInterfaceStatsRxFragment Counter64, + mtxrInterfaceStatsRxOverflow Counter64, + mtxrInterfaceStatsRxControl Counter64, + mtxrInterfaceStatsRxUnknownOp Counter64, + mtxrInterfaceStatsRxLengthError Counter64, + mtxrInterfaceStatsRxCodeError Counter64, + mtxrInterfaceStatsRxCarrierError Counter64, + mtxrInterfaceStatsRxJabber Counter64, + mtxrInterfaceStatsRxDrop Counter64, + + mtxrInterfaceStatsTxBytes Counter64, + mtxrInterfaceStatsTxPackets Counter64, + mtxrInterfaceStatsTxTooShort Counter64, + mtxrInterfaceStatsTx64 Counter64, + mtxrInterfaceStatsTx65To127 Counter64, + mtxrInterfaceStatsTx128To255 Counter64, + mtxrInterfaceStatsTx256To511 Counter64, + mtxrInterfaceStatsTx512To1023 Counter64, + mtxrInterfaceStatsTx1024To1518 Counter64, + mtxrInterfaceStatsTx1519ToMax Counter64, + mtxrInterfaceStatsTxTooLong Counter64, + mtxrInterfaceStatsTxBroadcast Counter64, + mtxrInterfaceStatsTxPause Counter64, + mtxrInterfaceStatsTxMulticast Counter64, + mtxrInterfaceStatsTxUnderrun Counter64, + mtxrInterfaceStatsTxCollision Counter64, + mtxrInterfaceStatsTxExcessiveCollision Counter64, + mtxrInterfaceStatsTxMultipleCollision Counter64, + mtxrInterfaceStatsTxSingleCollision Counter64, + mtxrInterfaceStatsTxExcessiveDeferred Counter64, + mtxrInterfaceStatsTxDeferred Counter64, + mtxrInterfaceStatsTxLateCollision Counter64, + mtxrInterfaceStatsTxTotalCollision Counter64, + mtxrInterfaceStatsTxPauseHonored Counter64, + mtxrInterfaceStatsTxDrop Counter64, + mtxrInterfaceStatsTxJabber Counter64, + mtxrInterfaceStatsTxFCSError Counter64, + mtxrInterfaceStatsTxControl Counter64, + mtxrInterfaceStatsTxFragment Counter64, + mtxrInterfaceStatsLinkDowns Counter32, + mtxrInterfaceStatsTxRx1024ToMax Counter64 +} + +mtxrInterfaceStatsIndex OBJECT-TYPE + SYNTAX ObjectIndex + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "" + ::= { mtxrInterfaceStatsEntry 1 } + +mtxrInterfaceStatsName OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrInterfaceStatsEntry 2 } + +mtxrInterfaceStatsDriverRxBytes OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrInterfaceStatsEntry 11 } + +mtxrInterfaceStatsDriverRxPackets OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrInterfaceStatsEntry 12 } + +mtxrInterfaceStatsDriverTxBytes OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrInterfaceStatsEntry 13 } + +mtxrInterfaceStatsDriverTxPackets OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrInterfaceStatsEntry 14 } + +mtxrInterfaceStatsTxRx64 OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrInterfaceStatsEntry 15 } + +mtxrInterfaceStatsTxRx65To127 OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrInterfaceStatsEntry 16 } + +mtxrInterfaceStatsTxRx128To255 OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrInterfaceStatsEntry 17 } + +mtxrInterfaceStatsTxRx256To511 OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrInterfaceStatsEntry 18 } + +mtxrInterfaceStatsTxRx512To1023 OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrInterfaceStatsEntry 19 } + +mtxrInterfaceStatsTxRx1024To1518 OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrInterfaceStatsEntry 20 } + +mtxrInterfaceStatsTxRx1519ToMax OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrInterfaceStatsEntry 21 } + +mtxrInterfaceStatsRxBytes OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrInterfaceStatsEntry 31 } + +mtxrInterfaceStatsRxPackets OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrInterfaceStatsEntry 32 } + +mtxrInterfaceStatsRxTooShort OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrInterfaceStatsEntry 33 } + +mtxrInterfaceStatsRx64 OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrInterfaceStatsEntry 34 } + +mtxrInterfaceStatsRx65To127 OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrInterfaceStatsEntry 35 } + +mtxrInterfaceStatsRx128To255 OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrInterfaceStatsEntry 36 } + +mtxrInterfaceStatsRx256To511 OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrInterfaceStatsEntry 37 } + +mtxrInterfaceStatsRx512To1023 OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrInterfaceStatsEntry 38 } + +mtxrInterfaceStatsRx1024To1518 OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrInterfaceStatsEntry 39 } + +mtxrInterfaceStatsRx1519ToMax OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrInterfaceStatsEntry 40 } + +mtxrInterfaceStatsRxTooLong OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrInterfaceStatsEntry 41 } + +mtxrInterfaceStatsRxBroadcast OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrInterfaceStatsEntry 42 } + +mtxrInterfaceStatsRxPause OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrInterfaceStatsEntry 43 } + +mtxrInterfaceStatsRxMulticast OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrInterfaceStatsEntry 44 } + +mtxrInterfaceStatsRxFCSError OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrInterfaceStatsEntry 45 } + +mtxrInterfaceStatsRxAlignError OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrInterfaceStatsEntry 46 } + +mtxrInterfaceStatsRxFragment OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrInterfaceStatsEntry 47 } + +mtxrInterfaceStatsRxOverflow OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrInterfaceStatsEntry 48 } + +mtxrInterfaceStatsRxControl OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrInterfaceStatsEntry 49 } + +mtxrInterfaceStatsRxUnknownOp OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrInterfaceStatsEntry 50 } + +mtxrInterfaceStatsRxLengthError OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrInterfaceStatsEntry 51 } + +mtxrInterfaceStatsRxCodeError OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrInterfaceStatsEntry 52 } + +mtxrInterfaceStatsRxCarrierError OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrInterfaceStatsEntry 53 } + +mtxrInterfaceStatsRxJabber OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrInterfaceStatsEntry 54 } + +mtxrInterfaceStatsRxDrop OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrInterfaceStatsEntry 55 } + +mtxrInterfaceStatsTxBytes OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrInterfaceStatsEntry 61 } + +mtxrInterfaceStatsTxPackets OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrInterfaceStatsEntry 62 } + +mtxrInterfaceStatsTxTooShort OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrInterfaceStatsEntry 63 } + +mtxrInterfaceStatsTx64 OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrInterfaceStatsEntry 64 } + +mtxrInterfaceStatsTx65To127 OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrInterfaceStatsEntry 65 } + +mtxrInterfaceStatsTx128To255 OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrInterfaceStatsEntry 66 } + +mtxrInterfaceStatsTx256To511 OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrInterfaceStatsEntry 67 } + +mtxrInterfaceStatsTx512To1023 OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrInterfaceStatsEntry 68 } + +mtxrInterfaceStatsTx1024To1518 OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrInterfaceStatsEntry 69 } + +mtxrInterfaceStatsTx1519ToMax OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrInterfaceStatsEntry 70 } + +mtxrInterfaceStatsTxTooLong OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrInterfaceStatsEntry 71 } + +mtxrInterfaceStatsTxBroadcast OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrInterfaceStatsEntry 72 } + +mtxrInterfaceStatsTxPause OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrInterfaceStatsEntry 73 } + +mtxrInterfaceStatsTxMulticast OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrInterfaceStatsEntry 74 } + +mtxrInterfaceStatsTxUnderrun OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrInterfaceStatsEntry 75 } + +mtxrInterfaceStatsTxCollision OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrInterfaceStatsEntry 76 } + +mtxrInterfaceStatsTxExcessiveCollision OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrInterfaceStatsEntry 77 } + +mtxrInterfaceStatsTxMultipleCollision OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrInterfaceStatsEntry 78 } + +mtxrInterfaceStatsTxSingleCollision OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrInterfaceStatsEntry 79 } + +mtxrInterfaceStatsTxExcessiveDeferred OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrInterfaceStatsEntry 80 } + +mtxrInterfaceStatsTxDeferred OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrInterfaceStatsEntry 81 } + +mtxrInterfaceStatsTxLateCollision OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrInterfaceStatsEntry 82 } + +mtxrInterfaceStatsTxTotalCollision OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrInterfaceStatsEntry 83 } + +mtxrInterfaceStatsTxPauseHonored OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrInterfaceStatsEntry 84 } + +mtxrInterfaceStatsTxDrop OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrInterfaceStatsEntry 85 } + +mtxrInterfaceStatsTxJabber OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrInterfaceStatsEntry 86 } + +mtxrInterfaceStatsTxFCSError OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrInterfaceStatsEntry 87 } + +mtxrInterfaceStatsTxControl OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrInterfaceStatsEntry 88 } + +mtxrInterfaceStatsTxFragment OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrInterfaceStatsEntry 89 } + +mtxrInterfaceStatsLinkDowns OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrInterfaceStatsEntry 90 } + +mtxrInterfaceStatsTxRx1024ToMax OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrInterfaceStatsEntry 91 } + +mtxrInterfaceStatsGroup OBJECT-GROUP OBJECTS { + mtxrInterfaceStatsName, + mtxrInterfaceStatsDriverRxBytes, + mtxrInterfaceStatsDriverRxPackets, + mtxrInterfaceStatsDriverTxBytes, + mtxrInterfaceStatsDriverTxPackets, + + mtxrInterfaceStatsTxRx64, + mtxrInterfaceStatsTxRx65To127, + mtxrInterfaceStatsTxRx128To255, + mtxrInterfaceStatsTxRx256To511, + mtxrInterfaceStatsTxRx512To1023, + mtxrInterfaceStatsTxRx1024To1518, + mtxrInterfaceStatsTxRx1519ToMax, + + mtxrInterfaceStatsRxBytes, + mtxrInterfaceStatsRxPackets, + mtxrInterfaceStatsRxTooShort, + mtxrInterfaceStatsRx64, + mtxrInterfaceStatsRx65To127, + mtxrInterfaceStatsRx128To255, + mtxrInterfaceStatsRx256To511, + mtxrInterfaceStatsRx512To1023, + mtxrInterfaceStatsRx1024To1518, + mtxrInterfaceStatsRx1519ToMax, + mtxrInterfaceStatsRxTooLong, + mtxrInterfaceStatsRxBroadcast, + mtxrInterfaceStatsRxPause, + mtxrInterfaceStatsRxMulticast, + mtxrInterfaceStatsRxFCSError, + mtxrInterfaceStatsRxAlignError, + mtxrInterfaceStatsRxFragment, + mtxrInterfaceStatsRxOverflow, + mtxrInterfaceStatsRxControl, + mtxrInterfaceStatsRxUnknownOp, + mtxrInterfaceStatsRxLengthError, + mtxrInterfaceStatsRxCodeError, + mtxrInterfaceStatsRxCarrierError, + mtxrInterfaceStatsRxJabber, + mtxrInterfaceStatsRxDrop, + + mtxrInterfaceStatsTxBytes, + mtxrInterfaceStatsTxPackets, + mtxrInterfaceStatsTxTooShort, + mtxrInterfaceStatsTx64, + mtxrInterfaceStatsTx65To127, + mtxrInterfaceStatsTx128To255, + mtxrInterfaceStatsTx256To511, + mtxrInterfaceStatsTx512To1023, + mtxrInterfaceStatsTx1024To1518, + mtxrInterfaceStatsTx1519ToMax, + mtxrInterfaceStatsTxTooLong, + mtxrInterfaceStatsTxBroadcast, + mtxrInterfaceStatsTxPause, + mtxrInterfaceStatsTxMulticast, + mtxrInterfaceStatsTxUnderrun, + mtxrInterfaceStatsTxCollision, + mtxrInterfaceStatsTxExcessiveCollision, + mtxrInterfaceStatsTxMultipleCollision, + mtxrInterfaceStatsTxSingleCollision, + mtxrInterfaceStatsTxExcessiveDeferred, + mtxrInterfaceStatsTxDeferred, + mtxrInterfaceStatsTxLateCollision, + mtxrInterfaceStatsTxTotalCollision, + mtxrInterfaceStatsTxPauseHonored, + mtxrInterfaceStatsTxDrop, + mtxrInterfaceStatsTxJabber, + mtxrInterfaceStatsTxFCSError, + mtxrInterfaceStatsTxControl, + mtxrInterfaceStatsTxFragment, + mtxrInterfaceStatsLinkDowns, + mtxrInterfaceStatsTxRx1024ToMax + } + STATUS current + DESCRIPTION "" + ::= { mtXRouterOsGroups 17 } + +-- POE ************************************************************************ + +mtxrPOETable OBJECT-TYPE + SYNTAX SEQUENCE OF MtxrPOEEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "Power Over Ethernet" + ::= { mtxrPOE 1 } + +mtxrPOEEntry OBJECT-TYPE + SYNTAX MtxrPOEEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "" + INDEX { mtxrPOEInterfaceIndex } + ::= { mtxrPOETable 1 } + +MtxrPOEEntry ::= SEQUENCE { + mtxrPOEInterfaceIndex ObjectIndex, + mtxrPOEName DisplayString, + mtxrPOEStatus INTEGER, + mtxrPOEVoltage Voltage, + mtxrPOECurrent Integer32, + mtxrPOEPower Power +} + +mtxrPOEInterfaceIndex OBJECT-TYPE + SYNTAX ObjectIndex + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "" + ::= { mtxrPOEEntry 1 } + +mtxrPOEName OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrPOEEntry 2 } + +mtxrPOEStatus OBJECT-TYPE + SYNTAX INTEGER { + disabled(1), + waitingForLoad(2), + poweredOn(3), + overload(4), + shortCircuit(5), + voltageTooLow(6), + currentTooLow(7), + powerReset(8), + voltageTooHigh(9), + controllerError(10), + controllerUpgrade(11), + poeInDetected(12), + noValidPsu(13), + controllerInit(14), + lowVoltageTooLow(15) + } + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrPOEEntry 3 } + +mtxrPOEVoltage OBJECT-TYPE + SYNTAX Voltage + MAX-ACCESS read-only + STATUS current + DESCRIPTION "V" + ::= { mtxrPOEEntry 4 } + +mtxrPOECurrent OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "mA" + ::= { mtxrPOEEntry 5 } + +mtxrPOEPower OBJECT-TYPE + SYNTAX Power + MAX-ACCESS read-only + STATUS current + DESCRIPTION "W" + ::= { mtxrPOEEntry 6 } + +mtxrPOEGroup OBJECT-GROUP OBJECTS { + mtxrPOEName, + mtxrPOEStatus, + mtxrPOEVoltage, + mtxrPOECurrent, + mtxrPOEPower + } + STATUS current + DESCRIPTION "" + ::= { mtXRouterOsGroups 18 } + +-- LTE Modem ************************************************************ + +mtxrLTEModemTable OBJECT-TYPE + SYNTAX SEQUENCE OF MtxrLTEModemEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "LTE Modems" + ::= { mtxrLTEModem 1 } + +mtxrLTEModemEntry OBJECT-TYPE + SYNTAX MtxrLTEModemEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "" + INDEX { mtxrLTEModemInterfaceIndex } + ::= { mtxrLTEModemTable 1 } + +MtxrLTEModemEntry ::= SEQUENCE { + mtxrLTEModemInterfaceIndex ObjectIndex, + mtxrLTEModemSignalRSSI Integer32, + mtxrLTEModemSignalRSRQ Integer32, + mtxrLTEModemSignalRSRP Integer32, + mtxrLTEModemCellId HexInt, + mtxrLTEModemAccessTechnology INTEGER, + mtxrLTEModemSignalSINR Integer32, + mtxrLTEModemEnbId Integer32, + mtxrLTEModemSectorId Integer32, + mtxrLTEModemLac Integer32, + mtxrLTEModemIMEI DisplayString, + mtxrLTEModemIMSI DisplayString, + mtxrLTEModemUICC DisplayString, + mtxrLTEModemRAT DisplayString +} + +mtxrLTEModemInterfaceIndex OBJECT-TYPE + SYNTAX ObjectIndex + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "" + ::= { mtxrLTEModemEntry 1 } + +mtxrLTEModemSignalRSSI OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "dBm" + ::= { mtxrLTEModemEntry 2 } + +mtxrLTEModemSignalRSRQ OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "dB" + ::= { mtxrLTEModemEntry 3 } + +mtxrLTEModemSignalRSRP OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "dBm" + ::= { mtxrLTEModemEntry 4 } + +mtxrLTEModemCellId OBJECT-TYPE + SYNTAX HexInt + MAX-ACCESS read-only + STATUS current + DESCRIPTION "current cell ID" + ::= { mtxrLTEModemEntry 5 } + +mtxrLTEModemAccessTechnology OBJECT-TYPE + SYNTAX INTEGER { + unknown(-1), + gsmcompact(0), + gsm(1), + utran(2), + egprs(3), + hsdpa(4), + hsupa(5), + hsdpahsupa(6), + eutran(7), + nr-sa(11), + nr-nsa(13) + } + MAX-ACCESS read-only + STATUS current + DESCRIPTION "as reported by +CREG" + ::= { mtxrLTEModemEntry 6 } + +mtxrLTEModemSignalSINR OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "dB" + ::= { mtxrLTEModemEntry 7 } + +mtxrLTEModemEnbId OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrLTEModemEntry 8 } + +mtxrLTEModemSectorId OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrLTEModemEntry 9 } + +mtxrLTEModemLac OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrLTEModemEntry 10 } + +mtxrLTEModemIMEI OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrLTEModemEntry 11 } + +mtxrLTEModemIMSI OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrLTEModemEntry 12 } + +mtxrLTEModemUICC OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrLTEModemEntry 13 } + +mtxrLTEModemRAT OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrLTEModemEntry 14 } + +mtxrLTEModemGroup OBJECT-GROUP OBJECTS { + mtxrLTEModemSignalRSSI, + mtxrLTEModemSignalRSRQ, + mtxrLTEModemSignalRSRP, + mtxrLTEModemCellId, + mtxrLTEModemAccessTechnology, + mtxrLTEModemSignalSINR, + mtxrLTEModemEnbId, + mtxrLTEModemSectorId, + mtxrLTEModemLac, + mtxrLTEModemIMEI, + mtxrLTEModemIMSI, + mtxrLTEModemUICC, + mtxrLTEModemRAT + } + STATUS current + DESCRIPTION "" + ::= { mtXRouterOsGroups 19 } + +-- Partition ************************************************************ + +mtxrPartitionTable OBJECT-TYPE + SYNTAX SEQUENCE OF MtxrPartitionEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "system partitions" + ::= { mtxrPartition 1 } + +mtxrPartitionEntry OBJECT-TYPE + SYNTAX MtxrPartitionEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "" + INDEX { mtxrPartitionIndex } + ::= { mtxrPartitionTable 1 } + +MtxrPartitionEntry ::= SEQUENCE { + mtxrPartitionIndex ObjectIndex, + mtxrPartitionName DisplayString, + mtxrPartitionSize Integer32, + mtxrPartitionVersion DisplayString, + mtxrPartitionActive BoolValue, + mtxrPartitionRunning BoolValue +} + +mtxrPartitionIndex OBJECT-TYPE + SYNTAX ObjectIndex + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "" + ::= { mtxrPartitionEntry 1 } + +mtxrPartitionName OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrPartitionEntry 2 } + +mtxrPartitionSize OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "MB" + ::= { mtxrPartitionEntry 3 } + +mtxrPartitionVersion OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrPartitionEntry 4 } + +mtxrPartitionActive OBJECT-TYPE + SYNTAX BoolValue + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrPartitionEntry 5 } + +mtxrPartitionRunning OBJECT-TYPE + SYNTAX BoolValue + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrPartitionEntry 6 } + +mtxrPartitionGroup OBJECT-GROUP OBJECTS { + mtxrPartitionName, + mtxrPartitionSize, + mtxrPartitionVersion, + mtxrPartitionActive, + mtxrPartitionRunning + } + STATUS current + DESCRIPTION "" + ::= { mtXRouterOsGroups 20 } + +-- OPTICAL ***************************************************************** + +mtxrOpticalTable OBJECT-TYPE + SYNTAX SEQUENCE OF MtxrOpticalTableEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "SFP and GPON information" + ::= { mtxrOptical 1 } + +mtxrOpticalTableEntry OBJECT-TYPE + SYNTAX MtxrOpticalTableEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "" + INDEX { mtxrOpticalIndex } + ::= { mtxrOpticalTable 1 } + +MtxrOpticalTableEntry ::= SEQUENCE { + mtxrOpticalIndex ObjectIndex, + mtxrOpticalName DisplayString, + mtxrOpticalRxLoss BoolValue, + mtxrOpticalTxFault BoolValue, + mtxrOpticalWavelength GDiv100, + mtxrOpticalTemperature Gauge32, + mtxrOpticalSupplyVoltage GDiv1000, + mtxrOpticalTxBiasCurrent Gauge32, + mtxrOpticalTxPower IDiv1000, + mtxrOpticalRxPower IDiv1000, + mtxrOpticalVendorName DisplayString, + mtxrOpticalVendorSerial DisplayString + +} + +mtxrOpticalGroup OBJECT-GROUP OBJECTS { + mtxrOpticalName, + mtxrOpticalRxLoss, + mtxrOpticalTxFault, + mtxrOpticalWavelength, + mtxrOpticalTemperature, + mtxrOpticalSupplyVoltage, + mtxrOpticalTxBiasCurrent, + mtxrOpticalTxPower, + mtxrOpticalRxPower, + mtxrOpticalVendorName, + mtxrOpticalVendorSerial + } + STATUS current + DESCRIPTION "" + ::= { mtXRouterOsGroups 6 } + +mtxrOpticalIndex OBJECT-TYPE + SYNTAX ObjectIndex + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "" + ::= { mtxrOpticalTableEntry 1 } + +mtxrOpticalName OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrOpticalTableEntry 2 } + +mtxrOpticalRxLoss OBJECT-TYPE + SYNTAX BoolValue + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrOpticalTableEntry 3 } + +mtxrOpticalTxFault OBJECT-TYPE + SYNTAX BoolValue + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrOpticalTableEntry 4 } + +mtxrOpticalWavelength OBJECT-TYPE + SYNTAX GDiv100 + UNITS "nm" + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrOpticalTableEntry 5 } + +mtxrOpticalTemperature OBJECT-TYPE + SYNTAX Gauge32 + UNITS "C" + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrOpticalTableEntry 6 } + +mtxrOpticalSupplyVoltage OBJECT-TYPE + SYNTAX GDiv1000 + UNITS "V" + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrOpticalTableEntry 7 } + +mtxrOpticalTxBiasCurrent OBJECT-TYPE + SYNTAX Gauge32 + UNITS "mA" + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrOpticalTableEntry 8 } + +mtxrOpticalTxPower OBJECT-TYPE + SYNTAX IDiv1000 + UNITS "dBm" + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrOpticalTableEntry 9 } + +mtxrOpticalRxPower OBJECT-TYPE + SYNTAX IDiv1000 + UNITS "dBm" + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrOpticalTableEntry 10 } + +mtxrOpticalVendorName OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrOpticalTableEntry 11 } + +mtxrOpticalVendorSerial OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrOpticalTableEntry 12 } + +-- IPSec ***************************************************************** + +mtxrIkeSACount OBJECT-TYPE + SYNTAX Gauge32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "IKE SA count" + ::= { mtxrIPSec 1 } + +mtxrIkeSATable OBJECT-TYPE + SYNTAX SEQUENCE OF MtxrIkeSATableEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "IKE SA table" + ::= { mtxrIPSec 2 } + +mtxrIkeSATableEntry OBJECT-TYPE + SYNTAX MtxrIkeSATableEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "" + INDEX { + mtxrIkeSAIndex + } + ::= { mtxrIkeSATable 1 } + +MtxrIkeSATableEntry ::= SEQUENCE { + mtxrIkeSAIndex ObjectIndex, + mtxrIkeSAInitiatorCookie IsakmpCookie, + mtxrIkeSAResponderCookie IsakmpCookie, + mtxrIkeSAResponder BoolValue, + mtxrIkeSANatt BoolValue, + mtxrIkeSAVersion Gauge32, + mtxrIkeSAState INTEGER, + mtxrIkeSAUptime TimeTicks, + mtxrIkeSASeen TimeTicks, + mtxrIkeSAIdentity DisplayString, + mtxrIkeSAPh2Count Gauge32, + mtxrIkeSALocalAddressType InetAddressType, + mtxrIkeSALocalAddress InetAddress, + mtxrIkeSALocalPort InetPortNumber, + mtxrIkeSAPeerAddressType InetAddressType, + mtxrIkeSAPeerAddress InetAddress, + mtxrIkeSAPeerPort InetPortNumber, + mtxrIkeSADynamicAddressType InetAddressType, + mtxrIkeSADynamicAddress InetAddress, + mtxrIkeSATxBytes Counter64, + mtxrIkeSARxBytes Counter64, + mtxrIkeSATxPackets Counter64, + mtxrIkeSARxPackets Counter64 +} + +mtxrIkeSAGroup OBJECT-GROUP OBJECTS { + mtxrIkeSACount, + mtxrIkeSAInitiatorCookie, + mtxrIkeSAResponderCookie, + mtxrIkeSAResponder, + mtxrIkeSANatt, + mtxrIkeSAVersion, + mtxrIkeSAState, + mtxrIkeSAUptime, + mtxrIkeSASeen, + mtxrIkeSAIdentity, + mtxrIkeSAPh2Count, + mtxrIkeSALocalAddressType, + mtxrIkeSALocalAddress, + mtxrIkeSALocalPort, + mtxrIkeSAPeerAddressType, + mtxrIkeSAPeerAddress, + mtxrIkeSAPeerPort, + mtxrIkeSADynamicAddressType, + mtxrIkeSADynamicAddress, + mtxrIkeSATxBytes, + mtxrIkeSARxBytes, + mtxrIkeSATxPackets, + mtxrIkeSARxPackets + } + STATUS current + DESCRIPTION "" + ::= { mtXRouterOsGroups 7 } + +mtxrIkeSAIndex OBJECT-TYPE + SYNTAX ObjectIndex + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "" + ::= { mtxrIkeSATableEntry 1 } + +mtxrIkeSAInitiatorCookie OBJECT-TYPE + SYNTAX IsakmpCookie + MAX-ACCESS read-only + STATUS current + DESCRIPTION "initiator SPI" + ::= { mtxrIkeSATableEntry 2 } + +mtxrIkeSAResponderCookie OBJECT-TYPE + SYNTAX IsakmpCookie + MAX-ACCESS read-only + STATUS current + DESCRIPTION "responder SPI" + ::= { mtxrIkeSATableEntry 3 } + +mtxrIkeSAResponder OBJECT-TYPE + SYNTAX BoolValue + MAX-ACCESS read-only + STATUS current + DESCRIPTION "IKE side" + ::= { mtxrIkeSATableEntry 4 } + +mtxrIkeSANatt OBJECT-TYPE + SYNTAX BoolValue + MAX-ACCESS read-only + STATUS current + DESCRIPTION "NAT is detected" + ::= { mtxrIkeSATableEntry 5 } + +mtxrIkeSAVersion OBJECT-TYPE + SYNTAX Gauge32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "protocol version" + ::= { mtxrIkeSATableEntry 6 } + +mtxrIkeSAState OBJECT-TYPE + SYNTAX INTEGER { + exchange(1), + established(2), + expired(3), + eap(4) + } + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrIkeSATableEntry 7 } + +mtxrIkeSAUptime OBJECT-TYPE + SYNTAX TimeTicks + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrIkeSATableEntry 8 } + +mtxrIkeSASeen OBJECT-TYPE + SYNTAX TimeTicks + MAX-ACCESS read-only + STATUS current + DESCRIPTION "time elapsed since last valid IKE packet" + ::= { mtxrIkeSATableEntry 9 } + +mtxrIkeSAIdentity OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "peer identity" + ::= { mtxrIkeSATableEntry 10 } + +mtxrIkeSAPh2Count OBJECT-TYPE + SYNTAX Gauge32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "total ph2 SA pairs" + ::= { mtxrIkeSATableEntry 11 } + +mtxrIkeSALocalAddressType OBJECT-TYPE + SYNTAX InetAddressType + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrIkeSATableEntry 12 } + +mtxrIkeSALocalAddress OBJECT-TYPE + SYNTAX InetAddress + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrIkeSATableEntry 13 } + +mtxrIkeSALocalPort OBJECT-TYPE + SYNTAX InetPortNumber + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrIkeSATableEntry 14 } + +mtxrIkeSAPeerAddressType OBJECT-TYPE + SYNTAX InetAddressType + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrIkeSATableEntry 15 } + +mtxrIkeSAPeerAddress OBJECT-TYPE + SYNTAX InetAddress + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrIkeSATableEntry 16 } + +mtxrIkeSAPeerPort OBJECT-TYPE + SYNTAX InetPortNumber + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrIkeSATableEntry 17 } + +mtxrIkeSADynamicAddressType OBJECT-TYPE + SYNTAX InetAddressType + MAX-ACCESS read-only + STATUS current + DESCRIPTION "" + ::= { mtxrIkeSATableEntry 18 } + +mtxrIkeSADynamicAddress OBJECT-TYPE + SYNTAX InetAddress + MAX-ACCESS read-only + STATUS current + DESCRIPTION "dynamic address allocated by mode config" + ::= { mtxrIkeSATableEntry 19 } + +mtxrIkeSATxBytes OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "ph2 SA tx bytes" + ::= { mtxrIkeSATableEntry 20 } + +mtxrIkeSARxBytes OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "ph2 SA rx bytes" + ::= { mtxrIkeSATableEntry 21 } + +mtxrIkeSATxPackets OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "ph2 SA tx packets" + ::= { mtxrIkeSATableEntry 22 } + +mtxrIkeSARxPackets OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "ph2 SA rx packets" + ::= { mtxrIkeSATableEntry 23 } + +mtxrWifiCapsman OBJECT IDENTIFIER ::= { mtxrWifi 1 } + +mtxrWifiCapsmanEnabled OBJECT-TYPE + SYNTAX TruthValue + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Indicates whether the Capsman is enabled." + ::= { mtxrWifiCapsman 1 } + +mtxrWifiCapsmanInterfaces OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "List of interfaces associated with Capsman." + ::= { mtxrWifiCapsman 2 } + +mtxrWifiCapsmanCACertificate OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "The CA certificate used by Capsman." + ::= { mtxrWifiCapsman 3 } + +mtxrWifiCapsmanCertificate OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "The local certificate used by Capsman." + ::= { mtxrWifiCapsman 4 } + +mtxrWifiCapsmanRequirePeerCertificate OBJECT-TYPE + SYNTAX TruthValue + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Whether a peer certificate is required." + ::= { mtxrWifiCapsman 5 } + +mtxrWifiCapsmanPackagePath OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Path to the Capsman package directory." + ::= { mtxrWifiCapsman 6 } + +mtxrWifiCapsmanUpgradePolicy OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Capsman upgrade policy." + ::= { mtxrWifiCapsman 7 } + +mtxrWifiCapsmanGeneratedCaCertificate OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Automatically generated CA certificate." + ::= { mtxrWifiCapsman 8 } + +mtxrWifiCapsmanGeneratedCertificate OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Automatically generated local certificate." + ::= { mtxrWifiCapsman 9 } + +mtxrWifiCap OBJECT IDENTIFIER ::= { mtxrWifi 2 } + +mtxrCapEnabled OBJECT-TYPE + SYNTAX TruthValue + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Indicates whether the CAP is enabled." + ::= { mtxrWifiCap 1 } + +mtxrCapInterfaces OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "List of interfaces used by the CAP." + ::= { mtxrWifiCap 2 } + +mtxrCapCertificate OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "The local certificate used by the CAP." + ::= { mtxrWifiCap 3 } + +mtxrCapCapsManAddresses OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Addresses of associated CapsMan controllers." + ::= { mtxrWifiCap 4 } + +mtxrCapCapsManNames OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Names of associated CapsMan controllers." + ::= { mtxrWifiCap 5 } + +mtxrCapCapsManCertificateCommonNames OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Common names of CapsMan certificates." + ::= { mtxrWifiCap 6 } + +mtxrCapLockToCapsMan OBJECT-TYPE + SYNTAX TruthValue + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Indicates if the CAP is locked to a specific CapsMan." + ::= { mtxrWifiCap 7 } + +mtxrCapSlavesStatic OBJECT-TYPE + SYNTAX TruthValue + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Indicates if CAP slaves are set to static mode." + ::= { mtxrWifiCap 8 } + +mtxrCapSlavesDatapath OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Datapath configuration of CAP slaves." + ::= { mtxrWifiCap 9 } + +mtxrCapRequestedCertificate OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Requested certificate for the CAP." + ::= { mtxrWifiCap 10 } + +mtxrCapLockedCapsManCommonName OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Locked CapsMan common name." + ::= { mtxrWifiCap 11 } + +mtxrCapCurrentCapsManAddress OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Current CapsMan address being used." + ::= { mtxrWifiCap 12 } + +mtxrCapCurrentCapsManIdentity OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Current identity of the connected CapsMan." + ::= { mtxrWifiCap 13 } + +-- Remote Caps ************************************************* + +mtxrRemoteCapTable OBJECT-TYPE + SYNTAX SEQUENCE OF MtxrWifiRemoteCapEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "" + ::= { mtxrWifi 3 } + +mtxrWifiRemoteCapEntry OBJECT-TYPE + SYNTAX MtxrWifiRemoteCapEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "Entry containing remote CAP statistics" + INDEX { mtxrRemoteCapId } + ::= { mtxrRemoteCapTable 1 } + +MtxrWifiRemoteCapEntry ::= SEQUENCE { + mtxrRemoteCapId ObjectIndex, + mtxrRemoteCapAddress DisplayString, + mtxrRemoteCapIdentity DisplayString, + mtxrRemoteCapBoardName DisplayString, + mtxrRemoteCapSerial DisplayString, + mtxrRemoteCapVersion DisplayString, + mtxrRemoteCapBaseMac MacAddress, + mtxrRemoteCapCommonName DisplayString, + mtxrRemoteCapState DisplayString +} + +mtxrRemoteCapId OBJECT-TYPE + SYNTAX ObjectIndex + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "ID of the remote CAP." + ::= { mtxrWifiRemoteCapEntry 1 } + +mtxrRemoteCapAddress OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "IP address of the remote CAP." + ::= { mtxrWifiRemoteCapEntry 2 } + +mtxrRemoteCapIdentity OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Identity name of the remote CAP." + ::= { mtxrWifiRemoteCapEntry 3 } + +mtxrRemoteCapBoardName OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Board name of the remote CAP." + ::= { mtxrWifiRemoteCapEntry 4 } + +mtxrRemoteCapSerial OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Serial number of the remote CAP." + ::= { mtxrWifiRemoteCapEntry 5 } + +mtxrRemoteCapVersion OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "RouterOS version of the remote CAP." + ::= { mtxrWifiRemoteCapEntry 6 } + +mtxrRemoteCapBaseMac OBJECT-TYPE + SYNTAX MacAddress + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Base MAC address of the remote CAP." + ::= { mtxrWifiRemoteCapEntry 7 } + +mtxrRemoteCapCommonName OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Certificate common name of the remote CAP." + ::= { mtxrWifiRemoteCapEntry 8 } + +mtxrRemoteCapState OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "State of the remote CAP (e.g., connected, disconnected)." + ::= { mtxrWifiRemoteCapEntry 9 } + +-- Wifi Registration Table ************************************************* + +mtxrWifiRegistrationTable OBJECT-TYPE + SYNTAX SEQUENCE OF MtxrWifiRegistrationTableEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "" + ::= { mtxrWifi 4 } + +mtxrWifiRegistrationTableEntry OBJECT-TYPE + SYNTAX MtxrWifiRegistrationTableEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "Entry containing wifi registration statistics" + INDEX { mtxrWifiRegistrationMacAddress, mtxrWifiRegistrationInterface } + ::= { mtxrWifiRegistrationTable 1 } + +MtxrWifiRegistrationTableEntry ::= SEQUENCE { + mtxrWifiRegistrationMacAddress MacAddress, + mtxrWifiRegistrationInterface ObjectIndex, + mtxrWifiRegistrationSsid DisplayString, + mtxrWifiRegistrationUptime TimeTicks, + mtxrWifiRegistrationLastActivity Integer32, + mtxrWifiRegistrationSignal Integer32, + mtxrWifiRegistrationAuthType DisplayString, + mtxrWifiRegistrationBand DisplayString, + mtxrWifiRegistrationTxRate Gauge32, + mtxrWifiRegistrationRxRate Gauge32, + mtxrWifiRegistrationTxPackets Counter64, + mtxrWifiRegistrationRxPackets Counter64, + mtxrWifiRegistrationTxBytes Counter64, + mtxrWifiRegistrationRxBytes Counter64, + mtxrWifiRegistrationTxBitsPerSecond Integer32, + mtxrWifiRegistrationRxBitsPerSecond Integer32, + mtxrWifiRegistrationVlanId Integer32, + mtxrWifiRegistrationAuthorized TruthValue +} + +mtxrWifiRegistrationMacAddress OBJECT-TYPE + SYNTAX MacAddress + MAX-ACCESS read-only + STATUS current + DESCRIPTION "MAC address of the registered device." + ::= { mtxrWifiRegistrationTableEntry 1 } + +mtxrWifiRegistrationInterface OBJECT-TYPE + SYNTAX ObjectIndex + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "Interface id of the registered device." + ::= { mtxrWifiRegistrationTableEntry 2 } + +mtxrWifiRegistrationSsid OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "SSID of the connected access point." + ::= { mtxrWifiRegistrationTableEntry 3 } + +mtxrWifiRegistrationUptime OBJECT-TYPE + SYNTAX TimeTicks + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Uptime of the registered connection." + ::= { mtxrWifiRegistrationTableEntry 4 } + +mtxrWifiRegistrationLastActivity OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Time since the last activity of the registered device." + ::= { mtxrWifiRegistrationTableEntry 5 } + +mtxrWifiRegistrationSignal OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Signal strength of the registered device." + ::= { mtxrWifiRegistrationTableEntry 6 } + +mtxrWifiRegistrationAuthType OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Authentication type used by the registered device." + ::= { mtxrWifiRegistrationTableEntry 7 } + +mtxrWifiRegistrationBand OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Wireless band used by the registered device." + ::= { mtxrWifiRegistrationTableEntry 8 } + +mtxrWifiRegistrationTxRate OBJECT-TYPE + SYNTAX Gauge32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Transmission rate of the registered device." + ::= { mtxrWifiRegistrationTableEntry 9 } + +mtxrWifiRegistrationRxRate OBJECT-TYPE + SYNTAX Gauge32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Reception rate of the registered device." + ::= { mtxrWifiRegistrationTableEntry 10 } + +mtxrWifiRegistrationTxPackets OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Number of transmitted packets." + ::= { mtxrWifiRegistrationTableEntry 11 } + +mtxrWifiRegistrationRxPackets OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Number of received packets." + ::= { mtxrWifiRegistrationTableEntry 12 } + +mtxrWifiRegistrationTxBytes OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Number of transmitted bytes." + ::= { mtxrWifiRegistrationTableEntry 13 } + +mtxrWifiRegistrationRxBytes OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Number of received bytes." + ::= {mtxrWifiRegistrationTableEntry 14 } + +mtxrWifiRegistrationTxBitsPerSecond OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Transmission rate in bits per second." + ::= { mtxrWifiRegistrationTableEntry 15 } + +mtxrWifiRegistrationRxBitsPerSecond OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Reception rate in bits per second." + ::= { mtxrWifiRegistrationTableEntry 16 } + +mtxrWifiRegistrationVlanId OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION "VLAN ID of the registered device." + ::= { mtxrWifiRegistrationTableEntry 17 } + +mtxrWifiRegistrationAuthorized OBJECT-TYPE + SYNTAX TruthValue + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Indicates whether the device is authorized." + ::= { mtxrWifiRegistrationTableEntry 18 } + +-- Wifi Interfaces *********************************************** + +mtxrWifiInterfaces OBJECT-TYPE + SYNTAX SEQUENCE OF MtxrWifiInterfacesEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "" + ::= { mtxrWifi 5 } + +mtxrWifiInterfacesEntry OBJECT-TYPE + SYNTAX MtxrWifiInterfacesEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "An entry representing WiFi interface" + INDEX { mtxrWifiInterfacesId } + ::= { mtxrWifiInterfaces 1 } + +MtxrWifiInterfacesEntry ::= SEQUENCE { + mtxrWifiInterfacesId ObjectIndex, + mtxrWifiInterfacesName DisplayString, + mtxrWifiInterfacesSsid DisplayString, + mtxrWifiInterfacesFreq DisplayString +} + +mtxrWifiInterfacesId OBJECT-TYPE + SYNTAX ObjectIndex + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "Unique identifier for each WiFi interface" + ::= { mtxrWifiInterfacesEntry 1 } + +mtxrWifiInterfacesName OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Name of the WiFi interface" + ::= { mtxrWifiInterfacesEntry 2 } + +mtxrWifiInterfacesSsid OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "SSID associated with the WiFi interface" + ::= { mtxrWifiInterfacesEntry 3 } + +mtxrWifiInterfacesFreq OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Frequency used by the WiFi interface" + ::= { mtxrWifiInterfacesEntry 4 } + +-- TRAPS ********************************************************************** + +mtxrNotifications OBJECT IDENTIFIER ::= { mtxrTraps 0 } + +mtxrTrap NOTIFICATION-TYPE + STATUS current + DESCRIPTION "Mikrotik trap OID" + ::= { mtxrNotifications 1 } + +mtxrTemperatureException NOTIFICATION-TYPE + STATUS current + DESCRIPTION "Mikrotik CPU temperature exception trap" + ::= { mtxrNotifications 2 } + +mtxrTrapGroup NOTIFICATION-GROUP NOTIFICATIONS { + mtxrTrap, + mtxrTemperatureException + } + STATUS current + DESCRIPTION "" + ::= { mtXRouterOsGroups 14 } + +-- *************************************************************************** + +END + diff --git a/roles/routeros/files/routeros-poe-mqtt-publish.sh b/roles/routeros/files/routeros-poe-mqtt-publish.sh new file mode 100755 index 0000000..4395ba0 --- /dev/null +++ b/roles/routeros/files/routeros-poe-mqtt-publish.sh @@ -0,0 +1,60 @@ +#!/bin/sh + +set -eu +umask 077 + +community="public" +tlsdir="$(openssl version -d | sed -e 's/^OPENSSLDIR: "\(.\+\)"$/\1/')" +cafile="${tlsdir}/certs/ca.crt" +keyfile="${tlsdir}/private/$(hostname -f).key" +certfile="${tlsdir}/certs/$(hostname -f).crt" + +export LDAPTLS_KEY="$keyfile" +export LDAPTLS_CERT="$certfile" + +mqtt_send() { + topic="$1" + value="$2" + mosquitto_pub -h mqtt02.home.foo.sh -t "$topic" -m "$value" \ + --cafile "$cafile" --key "$keyfile" --cert "$certfile" +} + +snmp_get() { + host="$1" + key="$2" + snmpget -v 1 -c "$community" "$host" -Oqv -m MIKROTIK-MIB "$key" | tr -d '"' +} + +# only run script if first vrrp interface is in master state +if [ "${1:-}" != "-f" ]; then + for state in /run/keepalived/*.state ; do + if [ "$(cat "$state")" != "MASTER" ]; then + exit 0 + fi + break + done +fi + +ldapsearch -Q -LLL -Y EXTERNAL "(&(objectClass=device)(description=MikroTik *))" cn | \ + awk '{ if ($1 == "cn:") print $2 }' | while read -r name +do + snmpwalk -v 1 -c "$community" "$name" -Oq -m MIKROTIK-MIB \ + MIKROTIK-MIB::mtxrPOEStatus | while read -r port status + do + port="$(echo "$port" | cut -d "." -f 2)" + [ "$status" = "poweredOn" ] || continue + + device="$(snmp_get "$name" "SNMPv2-SMI::mib-2.31.1.1.1.18.${port}")" + [ -z "$device" ] && continue + location="$(ldapsearch -Q -LLL -Y EXTERNAL \ + "(&(objectClass=device)(cn=${device}))" l | \ + sed -n 's/^l: \(.\+\)/\1/p' | tr '[:upper:]' '[:lower:]' | tr ' ' '_')" + [ -z "$location" ] && continue + + for key in Current Power Voltage ; do + topic="home/${location}/${device}/$(echo "$key" | tr '[:upper:]' '[:lower:]')" + value="$(snmp_get "$name" "MIKROTIK-MIB::mtxrPOE${key}.${port}")" + mqtt_send "$topic" "$value" + done + done +done diff --git a/roles/routeros/meta/main.yml b/roles/routeros/meta/main.yml new file mode 100644 index 0000000..d2f9d51 --- /dev/null +++ b/roles/routeros/meta/main.yml @@ -0,0 +1,3 @@ +--- +dependencies: + - {role: ldap} diff --git a/roles/routeros/tasks/main.yml b/roles/routeros/tasks/main.yml new file mode 100644 index 0000000..f9693ad --- /dev/null +++ b/roles/routeros/tasks/main.yml @@ -0,0 +1,79 @@ +--- +- name: Install packages + ansible.builtin.package: + name: "{{ item }}" + state: installed + with_items: + - mosquitto + - net-snmp-utils + +- name: Install routeros mib + ansible.builtin.copy: + dest: /usr/share/snmp/mibs/MIKROTIK-MIB.txt + src: mikrotik.mib + mode: "0644" + owner: root + group: "{{ ansible_wheel }}" + +- name: Create group + ansible.builtin.group: + name: routeros + system: true + +- name: Create user + ansible.builtin.user: + name: routeros + comment: RouterOS Downloader + group: routeros + groups: hostkey + create_home: false + home: /var/empty + shell: /sbin/nologin + system: true + +- name: Create download directory + ansible.builtin.file: + path: /srv/web/oob.foo.sh/routeros + state: directory + mode: "0775" + owner: root + group: routeros + +- name: Install README.md + ansible.builtin.copy: + dest: /srv/web/oob.foo.sh/routeros/README.md + src: README.md + mode: "0644" + owner: root + group: "{{ ansible_wheel }}" + +- name: Install download script + ansible.builtin.copy: + dest: /usr/local/bin/download-routeros-firmware + src: download-routeros-firmware.sh + mode: "0755" + owner: root + group: "{{ ansible_wheel }}" + +- name: Install download cron job + ansible.builtin.cron: + name: download-routeros-firmware + job: /usr/local/bin/download-routeros-firmware + user: routeros + hour: "05" + minute: "25" + +- name: Install mqtt publish script + ansible.builtin.copy: + dest: /usr/local/bin/routeros-poe-mqtt-publish + src: routeros-poe-mqtt-publish.sh + mode: "0755" + owner: root + group: "{{ ansible_wheel }}" + +- name: Install mqtt publish cron job + ansible.builtin.cron: + name: routeros-poe-mqtt-publish + job: /usr/local/bin/routeros-poe-mqtt-publish + user: routeros + minute: "*/5" diff --git a/roles/rpm_build/tasks/main.yml b/roles/rpm_build/tasks/main.yml index b24e952..450048b 100644 --- a/roles/rpm_build/tasks/main.yml +++ b/roles/rpm_build/tasks/main.yml @@ -14,7 +14,7 @@ state: directory owner: root group: "{{ ansible_wheel }}" - mode: 0755 + mode: "0755" with_items: - /export/rpmbuild - /export/rpmbuild/SOURCES @@ -34,6 +34,6 @@ ansible.builtin.copy: dest: /root/.rpmmacros content: "%_topdir /srv/rpmbuild\n" - mode: 0600 + mode: "0600" owner: root group: "{{ ansible_wheel }}" diff --git a/roles/rsync/client/tasks/main.yml b/roles/rsync/client/tasks/main.yml index 1519109..32e4bdc 100644 --- a/roles/rsync/client/tasks/main.yml +++ b/roles/rsync/client/tasks/main.yml @@ -11,7 +11,7 @@ ansible.builtin.template: dest: /usr/local/libexec/rsync-ssl-tunnel src: rsync-ssl-tunnel.j2 - mode: 0755 + mode: "0755" owner: root group: root @@ -19,6 +19,6 @@ ansible.builtin.copy: dest: /usr/local/bin/rsync-ssl src: rsync-ssl - mode: 0755 + mode: "0755" owner: root group: root diff --git a/roles/rsync/server/tasks/main.yml b/roles/rsync/server/tasks/main.yml index 404f708..71f53fc 100644 --- a/roles/rsync/server/tasks/main.yml +++ b/roles/rsync/server/tasks/main.yml @@ -17,7 +17,7 @@ ansible.builtin.template: dest: /etc/rsyncd.conf src: rsyncd.conf.j2 - mode: 0644 + mode: "0644" owner: root group: root @@ -25,7 +25,7 @@ ansible.builtin.template: dest: /etc/stunnel/rsyncd.conf src: rsyncd-stunnel.conf.j2 - mode: 0644 + mode: "0644" owner: root group: root @@ -33,7 +33,7 @@ ansible.builtin.file: dest: /etc/systemd/system/rsyncd@.service.d state: directory - mode: 0755 + mode: "0755" owner: root group: root @@ -41,7 +41,7 @@ ansible.builtin.copy: dest: /etc/systemd/system/rsyncd@.service.d/stunnel.conf src: systemd-stunnel.conf - mode: 0644 + mode: "0644" owner: root group: root diff --git a/roles/rsync_backup/files/backup-daily.sh b/roles/rsync_backup/files/backup-daily.sh new file mode 100755 index 0000000..4840732 --- /dev/null +++ b/roles/rsync_backup/files/backup-daily.sh @@ -0,0 +1,150 @@ +#!/bin/sh + +set -eu + +umask 077 + +ROTATED=30 + +CONFDIR="/etc/rsync-backup" +DESTDIR="/srv/backup" +LOGDIR="/var/log/rsync-backup" +RUNDIR="/var/run/rsync-backup" + +find_rotated() { + # sort dailys from oldest to newest, daily.7 daily.6 daily.5 ... + find "$1" -mindepth 1 -maxdepth 1 -type d -name "daily.*" | sort -V -r +} + +rotate_dirs() { + for host in "$@"; do + # rotate dailys starting from oldest + if [ ! -d "${DESTDIR}/${host}" ]; then + continue + fi + find_rotated "${DESTDIR}/${host}" | while read -r dir; do + ext="${dir##*.}" + next="${dir%.*}.$((ext+1))" + mv "$dir" "$next" + done + done + # compress logs over 1 day old + find "$LOGDIR" -type f -name '*.log' -mtime +1 -execdir gzip -f {} ';' +} + +prune_dirs() { + for host in "$@"; do + # remove oldest dailys + find_rotated "${DESTDIR}/${host}" | while read -r dir ; do + num="$(basename "$dir" | sed -e 's/^daily.//')" + if [ "$num" -gt $ROTATED ]; then + rm -rf "$dir" + fi + done + done + # remove logs over ROTATED*2 days old + find "$LOGDIR" -type f -name '*.log.gz' -mtime +$((ROTATED*2)) -delete +} + +rsync_pull() { + dirs="" + opts="" + host="$1" + conf="${CONFDIR}/${host}.conf" + if [ -s "$conf" ] && [ -x "$conf" ]; then + # shellcheck source=/dev/null + . "$conf" || return + else + echo "skipped: ${1}" 1>&2 + return + fi + + lockdir="${RUNDIR}/${host}.lock" + mkdir -m 0755 "$lockdir" || return + + if [ "$host" = "$(hostname)" ]; then + # skip ssh for localhost + set -- $dirs + else + set -- $(for d in $dirs; do echo "${host}:${d}" ; done) + fi + + base="${DESTDIR}/${host}" + if [ ! -d "$base" ]; then + mkdir -m 0700 "$base" || return + fi + dest="${base}/daily.0" + last="${base}/daily.1" + if [ ! -d "$dest" ]; then + mkdir -m 0700 "$dest" || return + fi + if [ -d "$last" ]; then + # hardlink unchanged files to previous daily + opts="--ignore-existing --link-dest=${last}" + fi + + logfile="${LOGDIR}/${host}.$(date +%Y%m%d-%H%M%S).log" + if ! /usr/local/bin/rsync \ + -e "ssh -o BatchMode=yes -i ${CONFDIR}/id_ed25519" \ + -Raqxz --no-devices $opts \ + --log-file="$logfile" \ + "$@" "$dest" + then + echo "rsync log: ${logfile}" 1>&2 + fi + rmdir "$lockdir" +} + +if [ ! -d "$DESTDIR" ]; then + echo "ERROR: ${DESTDIR} does not exist" 1>&2 + exit 1 +fi + +if [ ! -d "$LOGDIR" ]; then + echo "ERROR: ${LOGDIR} does not exist" 1>&2 + exit 1 +fi + +if [ ! -d "$RUNDIR" ]; then + mkdir -m 0755 "$RUNDIR" +fi + +ALL=false +PRUNE=false +ROTATE=false +while getopts "apr" OPT; do + case "$OPT" in + a) + ALL=true + ;; + p) + PRUNE=true + ;; + r) + ROTATE=true + ;; + *) + echo "Usage: $(basename "$0") [-apr] [host ...]" 1>&2 + exit 1 + ;; + esac +done +shift $((OPTIND-1)) + +mkdir -m 0755 "${RUNDIR}/daily.lock" +trap 'rmdir "${RUNDIR}/daily.lock"' EXIT + +if [ $ALL ]; then + for conf in "${CONFDIR}"/*.conf ; do + host="$(basename "$conf" ".conf")" + set -- "$host" "$@" + done +fi + +$ROTATE && rotate_dirs "$@" + +for host in "$@" ; do + rsync_pull "$host" +done + +$PRUNE && prune_dirs "$@" diff --git a/roles/web_logs/meta/main.yml b/roles/rsync_backup/meta/main.yml similarity index 65% rename from roles/web_logs/meta/main.yml rename to roles/rsync_backup/meta/main.yml index 61cc3ce..a6cb84e 100644 --- a/roles/web_logs/meta/main.yml +++ b/roles/rsync_backup/meta/main.yml @@ -1,3 +1,4 @@ --- dependencies: + - {role: backup_base} - {role: ssh_known_hosts} diff --git a/roles/rsync_backup/tasks/main.yml b/roles/rsync_backup/tasks/main.yml new file mode 100644 index 0000000..d0cfa26 --- /dev/null +++ b/roles/rsync_backup/tasks/main.yml @@ -0,0 +1,51 @@ +--- +- name: Copy backup script + ansible.builtin.copy: + dest: /usr/local/sbin/backup-daily + src: backup-daily.sh + mode: "0755" + owner: root + group: "{{ ansible_wheel }}" + +- name: Create config directory + ansible.builtin.file: + path: /etc/rsync-backup + state: directory + mode: "0755" + owner: root + group: "{{ ansible_wheel }}" + +- name: Create logdir + ansible.builtin.file: + path: /var/log/rsync-backup + state: directory + mode: "0700" + owner: root + group: "{{ ansible_wheel }}" + +- name: Create ssh keys + ansible.builtin.command: + argv: + - ssh-keygen + - -t + - ed25519 + - -C + - "root@{{ inventory_hostname }}" + - -N + - "" + - -f + - /etc/rsync-backup/id_ed25519 + creates: /etc/rsync-backup/id_ed25519 + +- name: Fetch ssh public key + ansible.builtin.fetch: + src: /etc/rsync-backup/id_ed25519.pub + dest: ../files/ssh/rsync-backup.pub + flat: true + +- name: Install cron job + ansible.builtin.cron: + name: daily rsync backup + job: /usr/local/sbin/backup-daily -a -p -r + hour: "00" + minute: "30" diff --git a/roles/rsyslog/tasks/main.yml b/roles/rsyslog/tasks/main.yml index 7372753..6cb4537 100644 --- a/roles/rsyslog/tasks/main.yml +++ b/roles/rsyslog/tasks/main.yml @@ -11,7 +11,7 @@ ansible.builtin.copy: dest: /etc/rsyslog.d/all.log.conf content: "*.* /var/log/all.log\n" - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" notify: Restart rsyslog @@ -20,7 +20,7 @@ ansible.builtin.template: dest: /etc/rsyslog.d/remote.conf src: remote.conf.j2 - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" notify: Restart rsyslog @@ -34,6 +34,6 @@ ansible.builtin.copy: dest: /etc/logrotate.d/syslog.all src: logrotate - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" diff --git a/roles/rsyslog/tasks/udp-listen.yml b/roles/rsyslog/tasks/udp-listen.yml index cf9ac73..1585323 100644 --- a/roles/rsyslog/tasks/udp-listen.yml +++ b/roles/rsyslog/tasks/udp-listen.yml @@ -3,7 +3,7 @@ ansible.builtin.copy: dest: /etc/rsyslog.d/udp-listen.conf src: udp-listen.conf - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" notify: Restart rsyslog diff --git a/roles/rsyslog/templates/remote.conf.j2 b/roles/rsyslog/templates/remote.conf.j2 index f93141b..767b9b5 100644 --- a/roles/rsyslog/templates/remote.conf.j2 +++ b/roles/rsyslog/templates/remote.conf.j2 @@ -1,3 +1,6 @@ +# Log with FQDN +global(LocalHostName="{{ inventory_hostname }}") + # Certificates global(DefaultNetstreamDriverCAFile="{{ tls_bundle }}" DefaultNetstreamDriverCertFile="{{ tls_certs }}/{{ inventory_hostname }}.crt" diff --git a/roles/sane/tasks/main.yml b/roles/sane/tasks/main.yml new file mode 100644 index 0000000..2d707b5 --- /dev/null +++ b/roles/sane/tasks/main.yml @@ -0,0 +1,14 @@ +--- +- name: Install packagers + ansible.builtin.package: + name: "{{ item }}" + state: installed + with_items: + - sane-backends + - sane-backends-daemon + +- name: Enable service + ansible.builtin.systemd: + name: saned.socket + state: started + enabled: true diff --git a/roles/saslauthd/tasks/main.yml b/roles/saslauthd/tasks/main.yml index d0c7ce8..74023d2 100644 --- a/roles/saslauthd/tasks/main.yml +++ b/roles/saslauthd/tasks/main.yml @@ -19,7 +19,7 @@ ansible.builtin.template: dest: /etc/saslauthd.conf src: saslauthd.conf.j2 - mode: 0640 + mode: "0640" owner: root group: "{{ ansible_wheel }}" notify: Restart saslauthd diff --git a/roles/scanservjs/defaults/main.yml b/roles/scanservjs/defaults/main.yml new file mode 100644 index 0000000..efff6f8 --- /dev/null +++ b/roles/scanservjs/defaults/main.yml @@ -0,0 +1,2 @@ +--- +scanservjs_version: latest diff --git a/roles/scanservjs/handlers/main.yml b/roles/scanservjs/handlers/main.yml new file mode 100644 index 0000000..5cffd92 --- /dev/null +++ b/roles/scanservjs/handlers/main.yml @@ -0,0 +1,6 @@ +--- +- name: Restart scanservjs + ansible.builtin.systemd: + name: scanservjs-container + daemon-reload: true + state: restarted diff --git a/roles/zoneminder/meta/main.yml b/roles/scanservjs/meta/main.yml similarity index 53% rename from roles/zoneminder/meta/main.yml rename to roles/scanservjs/meta/main.yml index 39b2859..19b52d0 100644 --- a/roles/zoneminder/meta/main.yml +++ b/roles/scanservjs/meta/main.yml @@ -1,4 +1,4 @@ --- dependencies: - {role: apache} - - {role: rpmfusion_free_repo} + - {role: podman} diff --git a/roles/scanservjs/tasks/main.yml b/roles/scanservjs/tasks/main.yml new file mode 100644 index 0000000..9399983 --- /dev/null +++ b/roles/scanservjs/tasks/main.yml @@ -0,0 +1,45 @@ +--- +- name: Create group + ansible.builtin.group: + name: scanserv + +- name: Create user + ansible.builtin.user: + name: scanserv + comment: Podman Scanservjs + group: scanserv + shell: /sbin/nologin + +- name: Enable user lingering + ansible.builtin.command: + argv: + - loginctl + - enable-linger + - scanserv + creates: /var/lib/systemd/linger/scanserv + +- name: Create service file + ansible.builtin.template: + dest: /etc/systemd/system/scanservjs-container.service + src: scanservjs-container.service.j2 + mode: "0644" + owner: root + group: "{{ ansible_wheel }}" + notify: Restart scanservjs + +- name: Enable service + ansible.builtin.service: + name: scanservjs-container + state: started + enabled: true + +- name: Copy apache config + ansible.builtin.copy: + dest: /etc/httpd/conf.local.d/scanservjs-container.conf + content: | + ProxyPass /scanservjs/ http://127.0.0.1:8006/ + ProxyPassReverse /scanservjs/ http://127.0.0.1:8006/ + mode: "0644" + owner: root + group: "{{ ansible_wheel }}" + notify: Restart apache diff --git a/roles/scanservjs/templates/scanservjs-container.service.j2 b/roles/scanservjs/templates/scanservjs-container.service.j2 new file mode 100644 index 0000000..157cb4f --- /dev/null +++ b/roles/scanservjs/templates/scanservjs-container.service.j2 @@ -0,0 +1,19 @@ +[Unit] +Description=Scanserv Container +Wants=network-online.target +After=network-online.target + +[Service] +User=scanserv +ExecStartPre=/usr/bin/podman pull docker.io/sbs20/scanservjs:{{ scanservjs_version }} +ExecStart=/usr/bin/podman run \ + --rm -p 127.0.0.1:8006:8080 \ + --network slirp4netns:allow_host_loopback=true \ + --env "SANED_NET_HOSTS={{ inventory_hostname }}" \ + --name scanservjs \ + docker.io/sbs20/scanservjs:{{ scanservjs_version }} +ExecStop=/usr/bin/podman stop --ignore scanservjs +ExecStopPost=/usr/bin/podman rm -f --ignore scanservjs + +[Install] +WantedBy=multi-user.target diff --git a/roles/selinux/tasks/main.yml b/roles/selinux/tasks/main.yml index a99d822..a45757c 100644 --- a/roles/selinux/tasks/main.yml +++ b/roles/selinux/tasks/main.yml @@ -8,6 +8,6 @@ ansible.builtin.file: dest: /usr/local/share/selinux state: directory - mode: 0755 + mode: "0755" owner: root group: "{{ ansible_wheel }}" diff --git a/roles/sendmail/files/update-sendmail-certs.sh b/roles/sendmail/files/update-sendmail-certs.sh new file mode 100644 index 0000000..0e0bbc9 --- /dev/null +++ b/roles/sendmail/files/update-sendmail-certs.sh @@ -0,0 +1,25 @@ +#!/bin/sh + +set -eu +umask 022 + +tmpdir="$(mktemp -d -p /etc/mail)" +trap 'rm -rf "$tmpdir"' EXIT +chmod 0755 "$tmpdir" + +awk '{ + if ($0 == "-----BEGIN CERTIFICATE-----") cert="" + else if ($0 == "-----END CERTIFICATE-----") print cert + else cert=cert$0 +}' /etc/pki/tls/certs/ca-bundle.crt /etc/pki/tls/certs/ca.crt | while read -r CERT; do + echo "$CERT" | base64 -d | openssl x509 -inform DER > \ + "${tmpdir}/$(echo "$CERT" | base64 -d | openssl x509 -inform DER -hash -noout).0" +done + +if ! diff -q "$tmpdir" "/etc/mail/certs" > /dev/null 2>&1 ; then + rm -rf /etc/mail/certs + mv "$tmpdir" /etc/mail/certs + exit 0 +fi + +exit 1 diff --git a/roles/sendmail/handlers/main.yml b/roles/sendmail/handlers/main.yml index fb8e4f1..3c47d7f 100644 --- a/roles/sendmail/handlers/main.yml +++ b/roles/sendmail/handlers/main.yml @@ -11,9 +11,21 @@ - -C - /etc/mail - all + register: result + changed_when: result.rc == 0 notify: Restart sendmail - name: Update aliases ansible.builtin.command: argv: - newaliases + register: result + changed_when: result.rc == 0 + +- name: Update sendmail root certs + ansible.builtin.command: + argv: + - update-sendmail-certs + register: result + failed_when: false + changed_when: result.rc == 0 diff --git a/roles/sendmail/meta/main.yml b/roles/sendmail/meta/main.yml index 4dc7ba0..ad8bde3 100644 --- a/roles/sendmail/meta/main.yml +++ b/roles/sendmail/meta/main.yml @@ -1,5 +1,5 @@ --- - dependencies: - {role: dhparams} + - {role: pki} - {role: saslauthd} diff --git a/roles/sendmail/tasks/main.yml b/roles/sendmail/tasks/main.yml index ee11f6e..c247eed 100644 --- a/roles/sendmail/tasks/main.yml +++ b/roles/sendmail/tasks/main.yml @@ -12,15 +12,31 @@ ansible.builtin.file: path: /etc/mail/certs state: directory - mode: 0755 + mode: "0755" owner: root group: "{{ ansible_wheel }}" +- name: Add script to update root certs + ansible.builtin.copy: + dest: /usr/local/sbin/update-sendmail-certs + src: update-sendmail-certs.sh + mode: "0755" + owner: root + group: "{{ ansible_wheel }}" + notify: Update sendmail root certs + +- name: Add cronjob to update root certs + ansible.builtin.cron: + name: update-sendmail-certs + job: /usr/local/sbin/update-sendmail-certs + hour: "05" + minute: "30" + - name: Copy private key ansible.builtin.copy: dest: "{{ tls_private }}/{{ mail_server }}.key" src: "{{ item }}" - mode: 0600 + mode: "0600" owner: root group: "{{ ansible_wheel }}" with_first_found: @@ -34,7 +50,7 @@ ansible.builtin.copy: src: "{{ item }}" dest: "{{ tls_certs }}/{{ mail_server }}.crt" - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" validate: /usr/bin/openssl x509 -in %s -noout @@ -49,7 +65,7 @@ ansible.builtin.copy: src: "{{ item }}" dest: "{{ tls_certs }}/{{ mail_server }}-chain.crt" - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" validate: /usr/bin/openssl x509 -in %s -noout @@ -68,7 +84,7 @@ ansible.builtin.file: path: /export/mail state: directory - mode: 0775 + mode: "0775" owner: root group: mail setype: _default @@ -96,7 +112,7 @@ ansible.builtin.template: src: sendmail.mc.j2 dest: /etc/mail/sendmail.mc - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" validate: /bin/sh -c '/usr/bin/m4 %s > /dev/null' @@ -106,7 +122,7 @@ ansible.builtin.copy: src: "{{ ansible_private }}/files/sendmail/aliases" dest: /etc/aliases - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" notify: Update aliases diff --git a/roles/sendmail/templates/sendmail.mc.j2 b/roles/sendmail/templates/sendmail.mc.j2 index c0d9b08..ad31555 100644 --- a/roles/sendmail/templates/sendmail.mc.j2 +++ b/roles/sendmail/templates/sendmail.mc.j2 @@ -60,9 +60,11 @@ FEATURE(`accept_unresolvable_domains')dnl dnl # define(`confMATCH_GECOS')dnl define(`confDOMAIN_NAME', `{{ mail_domain }}')dnl +define(`confHELO_NAME', `mail.{{ mail_domain }}')dnl define(`confDONT_BLAME_SENDMAIL', `GroupWritableDirpathSafe,GroupWritableIncludeFile,GroupWritableIncludeFileSafe')dnl dnl # MAIL_FILTER(`grossd', `S=inet:5523@localhost, T=C:10m;R:5m') +INPUT_MAIL_FILTER(`opendkim', `S=local:/run/opendkim/opendkim.sock') dnl MAILER(smtp)dnl MAILER(procmail)dnl diff --git a/roles/sftpbackup/files/backup-sftp.sh b/roles/sftpbackup/files/backup-sftp.sh deleted file mode 100644 index 0dcc172..0000000 --- a/roles/sftpbackup/files/backup-sftp.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/bin/sh - -set -u -umas 077 - -TARGET="/export/backup" -CONFIG="/etc/rclone/rclone.conf" -LOGDIR="/var/log/rclone" -RCLONE="/usr/local/bin/rclone" - -timestamp="$(date %Y%m%d)" - -if [ ! -d "$TARGET" ]; then - echo "ERR: Destination directory '${TARGET}' does not exist" 1>&2 - exit 1 -fi - -for host in $("$RCLONE" --config "$CONFIG" listremotes | tr -d ":") ; do - fqdn="$("$RCLONE" --config "$CONFIG" config show "$host" | \ - awk '{ if ($1 == "host") print $3 }')" - if [ ! -d "${TARGET}/${fqdn}" ]; then - mkdir "${TARGET}/${fqdn}" - fi - log="${LOGDIR}/${fqdn}.${timestamp}.log" - if ! "$RCLONE" --config "$CONFIG" --log-file "$log" --log-level INFO \ - sync "${host}:/" "${TARGET}/${fqdn}/"; then - cat "$log" - fi -done diff --git a/roles/sftpbackup/tasks/main.yml b/roles/sftpbackup/tasks/main.yml deleted file mode 100644 index e131de3..0000000 --- a/roles/sftpbackup/tasks/main.yml +++ /dev/null @@ -1,9 +0,0 @@ ---- -- name: Import rclone role - ansible.builtin.import_role: - name: rclone - vars: - hostgroup: sftpbackup - remote_user: backup - destination: /export/backup - private_key: /root/.ssh/id_ed25519 diff --git a/roles/sftpuser/tasks/main.yml b/roles/sftpuser/tasks/main.yml deleted file mode 100644 index 6cf95fd..0000000 --- a/roles/sftpuser/tasks/main.yml +++ /dev/null @@ -1,35 +0,0 @@ ---- -- name: "Create group {{ user }}" - ansible.builtin.group: - name: "{{ user }}" - system: true - -- name: "Create user {{ user }}" - ansible.builtin.user: - name: "{{ user }}" - comment: "Service {{ user }}" - createhome: false - group: "{{ user }}" - home: /var/empty - shell: /sbin/nologin - system: true - -- name: "Create authorized_keys for {{ user }}" - ansible.builtin.copy: - dest: "/etc/ssh/authorized_keys.{{ user }}" - content: "{{ publickeys | join('\n') + '\n'}}" - mode: 0640 - owner: root - group: "{{ user }}" - -- name: Configure sshd chroot - ansible.builtin.blockinfile: - path: /etc/ssh/sshd_config - block: | - Match User {{ user }} - ChrootDirectory {{ chroot }} - ForceCommand internal-sftp - AuthorizedKeysFile /etc/ssh/authorized_keys.{{ user }} - marker: "# {mark} ANSIBLE MANAGED BLOCK (user {{ user }})" - validate: "sshd -t -f %s" - notify: Restart sshd diff --git a/roles/shelly_firmware/files/download-shelly-firmware.sh b/roles/shelly_firmware/files/download-shelly-firmware.sh new file mode 100644 index 0000000..608b156 --- /dev/null +++ b/roles/shelly_firmware/files/download-shelly-firmware.sh @@ -0,0 +1,26 @@ +#!/bin/sh + +set -eu + +umask 022 + +cd /srv/web/iot.foo.sh/shelly + +PATH="/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin" + +URL="http://archive.shelly-tools.de/" + +for _prod in $(curl -sSf "${URL}/archive.php" | jq -r '.[].type') ; do + _ver="$(curl -sSf "${URL}/archive.php?type=${_prod}" | jq -r \ + 'max_by(.version[1:] | split(".") | map(try tonumber catch 0)) .version')" + _name="$(curl -sSf "${URL}/archive.php?type=${_prod}" | jq -r \ + 'limit(1; .[].file)')" + if [ ! -f "${_prod}.${_ver}.zip" ]; then + echo "New firmware for ${_prod} (version ${_ver})" + curl -sSf -o "${_prod}.${_ver}.zip" "${URL}/version/${_ver}/${_name}" + if [ -h "$_name" ]; then + rm -f "$_name" + fi + ln -s "${_prod}.${_ver}.zip" "$_name" + fi +done diff --git a/roles/shelly_firmware/tasks/main.yml b/roles/shelly_firmware/tasks/main.yml new file mode 100644 index 0000000..db0e0ea --- /dev/null +++ b/roles/shelly_firmware/tasks/main.yml @@ -0,0 +1,28 @@ +--- +- name: Install dependencies + ansible.builtin.package: + name: jq + state: installed + +- name: Create download directory + ansible.builtin.file: + path: /srv/web/iot.foo.sh/shelly + state: directory + mode: "0755" + owner: root + group: "{{ ansible_wheel }}" + +- name: Install download script + ansible.builtin.copy: + dest: /usr/local/bin/download-shelly-firmware + src: download-shelly-firmware.sh + mode: "0755" + owner: root + group: "{{ ansible_wheel }}" + +- name: Install cron job + ansible.builtin.cron: + name: download-shelly-firmware + job: /usr/local/bin/download-shelly-firmware + hour: "05" + minute: 20 diff --git a/roles/snmp_exporter/defaults/main.yml b/roles/snmp_exporter/defaults/main.yml new file mode 100644 index 0000000..de468b0 --- /dev/null +++ b/roles/snmp_exporter/defaults/main.yml @@ -0,0 +1,2 @@ +--- +snmp_exporter_pkg: "snmp_exporter-{{ snmp_exporter_version }}.linux-amd64" diff --git a/roles/snmp_exporter/files/snmp_exporter.service b/roles/snmp_exporter/files/snmp_exporter.service new file mode 100644 index 0000000..f96318e --- /dev/null +++ b/roles/snmp_exporter/files/snmp_exporter.service @@ -0,0 +1,14 @@ +[Unit] +Description=Prometheus SNMP Exporter +After=syslog.target +After=network.target + +[Service] +Type=simple +User=snmp +Group=snmp +ExecStart=/usr/local/bin/snmp_exporter --config.file=/etc/snmp_exporter/snmp.yml --web.config.file=/etc/snmp_exporter/web-config.yml +Restart=always + +[Install] +WantedBy=multi-user.target diff --git a/roles/snmp_exporter/handlers/main.yml b/roles/snmp_exporter/handlers/main.yml new file mode 100644 index 0000000..13fdec5 --- /dev/null +++ b/roles/snmp_exporter/handlers/main.yml @@ -0,0 +1,6 @@ +--- +- name: Restart snmp_exporter + ansible.builtin.systemd: + name: snmp_exporter + daemon_reload: true + state: restarted diff --git a/roles/snmp_exporter/tasks/main.yml b/roles/snmp_exporter/tasks/main.yml new file mode 100644 index 0000000..57a557b --- /dev/null +++ b/roles/snmp_exporter/tasks/main.yml @@ -0,0 +1,104 @@ +--- +- name: Create group + ansible.builtin.group: + name: snmp + +- name: Create user + ansible.builtin.user: + name: snmp + comment: Prometheus SNMP Exporter + group: snmp + create_home: false + home: /var/empty + shell: /sbin/nologin + +- name: Download package + ansible.builtin.get_url: + url: >- + {{ + "https://github.com/prometheus/snmp_exporter/releases/download/v" + + snmp_exporter_version + "/" + snmp_exporter_pkg + ".tar.gz" + }} + dest: "/usr/local/src/{{ snmp_exporter_pkg }}.tar.gz" + mode: "0644" + owner: root + group: "{{ ansible_wheel }}" + +- name: Extract package + ansible.builtin.unarchive: + src: "/usr/local/src/{{ snmp_exporter_pkg }}.tar.gz" + dest: /usr/local/src + owner: root + group: "{{ ansible_wheel }}" + creates: "/usr/local/src/{{ snmp_exporter_pkg }}" + remote_src: true + +- name: Copy binary + ansible.builtin.copy: + dest: /usr/local/bin/snmp_exporter + src: "/usr/local/src/{{ snmp_exporter_pkg }}/snmp_exporter" + mode: "0755" + owner: root + group: "{{ ansible_wheel }}" + remote_src: true + notify: Restart snmp_exporter + +- name: Create config directory + ansible.builtin.file: + path: /etc/snmp_exporter + state: directory + mode: "0755" + owner: root + group: "{{ ansible_wheel }}" + +- name: Copy TLS private key + ansible.builtin.copy: + src: "/srv/ca/private/nms.home.foo.sh.key" + dest: "{{ tls_private }}/nms.home.foo.sh.key" + mode: "0640" + owner: root + group: snmp + notify: Restart snmp_exporter + +- name: Copy TLS certificate + ansible.builtin.copy: + src: "/srv/ca/certs/hosts/nms.home.foo.sh.crt" + dest: "{{ tls_certs }}/nms.home.foo.sh.crt" + mode: "0644" + owner: root + group: "{{ ansible_wheel }}" + notify: Restart snmp_exporter + +- name: Create web-config + ansible.builtin.template: + dest: /etc/snmp_exporter/web-config.yml + src: web-config.yml.j2 + mode: "0644" + owner: root + group: "{{ ansible_wheel }}" + notify: Restart snmp_exporter + +- name: Copy config + ansible.builtin.copy: + src: "/usr/local/src/{{ snmp_exporter_pkg }}/snmp.yml" + dest: /etc/snmp_exporter/snmp.yml + mode: "0644" + owner: root + group: "{{ ansible_wheel }}" + remote_src: true + notify: Restart snmp_exporter + +- name: Create service file + ansible.builtin.copy: + dest: /etc/systemd/system/snmp_exporter.service + src: snmp_exporter.service + mode: "0644" + owner: root + group: "{{ ansible_wheel }}" + notify: Restart snmp_exporter + +- name: Enable service + ansible.builtin.service: + name: snmp_exporter + state: started + enabled: true diff --git a/roles/snmp_exporter/templates/web-config.yml.j2 b/roles/snmp_exporter/templates/web-config.yml.j2 new file mode 100644 index 0000000..eb60f11 --- /dev/null +++ b/roles/snmp_exporter/templates/web-config.yml.j2 @@ -0,0 +1,11 @@ +--- +tls_server_config: + key_file: {{ tls_private }}/nms.home.foo.sh.key + cert_file: {{ tls_certs }}/nms.home.foo.sh.crt + client_ca_file: {{ tls_certs }}/ca.crt + client_auth_type: RequireAndVerifyClientCert + client_allowed_sans: +{% for host in groups['prometheus'] %} + - {{ host }} +{% endfor %} + min_version: TLS13 diff --git a/roles/spamassassin/tasks/main.yml b/roles/spamassassin/tasks/main.yml index efd698c..93310d5 100644 --- a/roles/spamassassin/tasks/main.yml +++ b/roles/spamassassin/tasks/main.yml @@ -8,7 +8,7 @@ ansible.builtin.copy: dest: /etc/mail/spamassassin/local.cf src: local.cf - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" notify: Restart spamassassin diff --git a/roles/spamassassin_clamav/tasks/main.yml b/roles/spamassassin_clamav/tasks/main.yml index 63e9e77..e8db4df 100644 --- a/roles/spamassassin_clamav/tasks/main.yml +++ b/roles/spamassassin_clamav/tasks/main.yml @@ -3,7 +3,7 @@ ansible.builtin.copy: src: ClamAV.pm dest: /etc/mail/spamassassin/ClamAV.pm - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" notify: Restart spamassassin @@ -12,7 +12,7 @@ ansible.builtin.copy: src: clamav.cf dest: /etc/mail/spamassassin/clamav.cf - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" notify: Restart spamassassin diff --git a/roles/spamassassin_razor/tasks/main.yml b/roles/spamassassin_razor/tasks/main.yml index b6268dc..dce1cfe 100644 --- a/roles/spamassassin_razor/tasks/main.yml +++ b/roles/spamassassin_razor/tasks/main.yml @@ -8,7 +8,7 @@ ansible.builtin.file: path: /var/lib/razor state: directory - mode: 0755 + mode: "0755" owner: root group: "{{ ansible_wheel }}" setype: _default diff --git a/roles/spamassassin_textcat/tasks/main.yml b/roles/spamassassin_textcat/tasks/main.yml index 2e3daad..08e645f 100644 --- a/roles/spamassassin_textcat/tasks/main.yml +++ b/roles/spamassassin_textcat/tasks/main.yml @@ -3,7 +3,7 @@ ansible.builtin.copy: dest: /etc/mail/spamassassin/textcat.pre content: "loadplugin Mail::SpamAssassin::Plugin::TextCat\n" - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" notify: Restart spamassassin diff --git a/roles/ssh_known_hosts/tasks/main.yml b/roles/ssh_known_hosts/tasks/main.yml deleted file mode 100644 index e5caeff..0000000 --- a/roles/ssh_known_hosts/tasks/main.yml +++ /dev/null @@ -1,8 +0,0 @@ ---- -- name: Create SSH known_hosts - ansible.builtin.template: - dest: /etc/ssh/ssh_known_hosts - src: ssh_known_hosts.j2 - mode: 0644 - owner: root - group: "{{ ansible_wheel }}" diff --git a/roles/ssh_known_hosts/templates/ssh_known_hosts.j2 b/roles/ssh_known_hosts/templates/ssh_known_hosts.j2 deleted file mode 100644 index d6fc971..0000000 --- a/roles/ssh_known_hosts/templates/ssh_known_hosts.j2 +++ /dev/null @@ -1,5 +0,0 @@ -{% for host, vars in hostvars|dictsort %} -{% if vars["ansible_ssh_host_key_ed25519_public"] is defined %} -{{ host }} ssh-ed25519 {{ vars["ansible_ssh_host_key_ed25519_public"] }} -{% endif %} -{% endfor %} diff --git a/roles/sshca/files/genkey.sh b/roles/sshca/files/genkey.sh new file mode 100755 index 0000000..29bd3ed --- /dev/null +++ b/roles/sshca/files/genkey.sh @@ -0,0 +1,28 @@ +#!/bin/sh + +set -eu + +if [ $# -ne 1 ]; then + echo "Usage: $(basename "$0") " 1>&2 + exit +fi + +cd /srv/sshca/ca + +year="$1" +if [ "$year" -eq "$year" ] 2> /dev/null; then + if [ "$year" -lt "$(date +%Y)" ]; then + echo "ERROR: Invalid year \"${year}\", time in the past" 1>&2 + exit 1 + fi +else + echo "ERROR: Invalid year \"${year}\"" 1>&2 + exit 1 +fi + +if [ -f "ca.${year}" ]; then + echo "ERROR: Key \"${year}\" already exists" 1>&2 + exit 1 +fi + +ssh-keygen -t ed25519 -f "/srv/sshca/ca/ca.${year}" -C "foo.sh - SSH CA ${year}" diff --git a/roles/sshca/tasks/main.yml b/roles/sshca/tasks/main.yml new file mode 100644 index 0000000..41edb8b --- /dev/null +++ b/roles/sshca/tasks/main.yml @@ -0,0 +1,36 @@ +--- +- name: Create datadirectories + ansible.builtin.file: + path: "{{ item }}" + state: directory + mode: "0755" + owner: root + group: "{{ ansible_wheel }}" + with_items: + - /export/sshca + - /export/sshca/pubkeys + +- name: Create CA directory + ansible.builtin.file: + path: "/export/sshca/ca" + state: directory + mode: "0700" + owner: root + group: "{{ ansible_wheel }}" + +- name: Link datadirectory + ansible.builtin.file: + dest: /srv/sshca + src: /export/sshca + state: link + owner: root + group: "{{ ansible_wheel }}" + follow: false + +- name: Copy key generation script + ansible.builtin.copy: + dest: /srv/sshca/ca/genkey.sh + src: genkey.sh + mode: "0755" + owner: root + group: "{{ ansible_wheel }}" diff --git a/roles/sshd/tasks/main.yml b/roles/sshd/tasks/main.yml index ff28d65..a90c594 100644 --- a/roles/sshd/tasks/main.yml +++ b/roles/sshd/tasks/main.yml @@ -28,8 +28,8 @@ line: "CRYPTO_POLICY=" notify: Restart sshd when: - - ansible_distribution == "CentOS" - - ansible_distribution_version is version_compare("8", ">=") + - ansible_distribution == "Rocky" + - ansible_distribution_version | int == 8 - name: Tighten ssh kex algorithm ansible.builtin.lineinfile: diff --git a/roles/sshd_cert/defaults/main.yml b/roles/sshd_cert/defaults/main.yml new file mode 100644 index 0000000..79b179b --- /dev/null +++ b/roles/sshd_cert/defaults/main.yml @@ -0,0 +1,2 @@ +--- +sshd_cert_hostnames: "{{ ssh_hostnames | default([]) + [inventory_hostname] }}" diff --git a/roles/sftpuser/meta/main.yml b/roles/sshd_cert/meta/main.yml similarity index 100% rename from roles/sftpuser/meta/main.yml rename to roles/sshd_cert/meta/main.yml diff --git a/roles/sshd_cert/tasks/main.yml b/roles/sshd_cert/tasks/main.yml new file mode 100644 index 0000000..964696e --- /dev/null +++ b/roles/sshd_cert/tasks/main.yml @@ -0,0 +1,81 @@ +--- +- name: Copy public key for signing + ansible.builtin.fetch: + src: /etc/ssh/ssh_host_ed25519_key.pub + dest: "/srv/sshca/pubkeys/{{ inventory_hostname }}.pub" + flat: true + +- name: Check status of public key + ansible.builtin.stat: + path: "/srv/sshca/pubkeys/{{ inventory_hostname }}.pub" + changed_when: false + failed_when: false + check_mode: false + delegate_to: localhost + register: sshd_cert_pubkey + +- name: Check status of certificate + ansible.builtin.stat: + path: "/srv/sshca/pubkeys/{{ inventory_hostname }}-cert.pub" + changed_when: false + failed_when: false + check_mode: false + delegate_to: localhost + register: sshd_cert_status + +- name: Get certificate info + ansible.builtin.command: + argv: + - ssh-keygen + - -L + - -f + - "/srv/sshca/pubkeys/{{ inventory_hostname }}-cert.pub" + changed_when: false + failed_when: false + check_mode: false + when: sshd_cert_status.stat.exists + delegate_to: localhost + register: sshd_cert_info + +- name: Sign certificate + ansible.builtin.command: + argv: + - ssh-keygen + - -s + - "/srv/sshca/ca/ca.{{ ansible_date_time['year'] }}" + - -I + - "{{ inventory_hostname }}" + - -h + - -n + - "{{ sshd_cert_hostnames | join(',') }}" + - -V + - -1h:+365d + - -z + - "{{ ansible_date_time.epoch }}" + - "/srv/sshca/pubkeys/{{ inventory_hostname }}.pub" + when: > + not sshd_cert_status.stat.exists or + sshd_cert_status.stat.mtime | int < sshd_cert_pubkey.stat.mtime | int or + ( + sshd_cert_info.stdout_lines | select('match', '^[ ]*Valid: ') | + first | split() | last | to_datetime('%Y-%m-%dT%H:%M:%S') + ).strftime('%s') | int < ansible_date_time.epoch | int + 2592000 + delegate_to: localhost + +- name: Install certificate + ansible.builtin.copy: + dest: /etc/ssh/ssh_host_ed25519_key-cert.pub + src: "/srv/sshca/pubkeys/{{ inventory_hostname }}-cert.pub" + mode: "0644" + owner: root + group: "{{ ansible_wheel }}" + notify: Restart sshd + +- name: Enable host certificate + ansible.builtin.lineinfile: + path: /etc/ssh/sshd_config + line: HostCertificate /etc/ssh/ssh_host_ed25519_key-cert.pub + regexp: "^(# )?HostCertificate .*" + insertafter: "^HostKey .*" + validate: "sshd -t -f %s" + notify: Restart sshd diff --git a/roles/sssd/tasks/main.yml b/roles/sssd/tasks/main.yml index dae5335..1ce5a2a 100644 --- a/roles/sssd/tasks/main.yml +++ b/roles/sssd/tasks/main.yml @@ -8,7 +8,7 @@ ansible.builtin.template: dest: /etc/sssd/sssd.conf src: sssd.conf.j2 - mode: 0600 + mode: "0600" owner: root group: "{{ ansible_wheel }}" notify: Restart sssd @@ -20,11 +20,15 @@ enabled: true - name: Get current state of authselect - ansible.builtin.shell: - cmd: /usr/bin/authselect current --raw ; /bin/true + ansible.builtin.command: + argv: + - /usr/bin/authselect + - current + - --raw register: result check_mode: false changed_when: false + failed_when: result.rc not in [0, 2] - name: Switch authselect to use sssd ansible.builtin.command: @@ -33,4 +37,6 @@ - select - sssd - --force + register: result + changed_when: result.rc == 0 when: result.stdout.split()[0] != "sssd" diff --git a/roles/sssd/templates/sssd.conf.j2 b/roles/sssd/templates/sssd.conf.j2 index 82aa6b1..38e7cf8 100644 --- a/roles/sssd/templates/sssd.conf.j2 +++ b/roles/sssd/templates/sssd.conf.j2 @@ -8,11 +8,11 @@ domains = {{ kerberos_realm }} [pam] [domain/{{ kerberos_realm }}] -id_provider = ldap -auth_provider = krb5 -chpass_provider = ldap autofs_provider = none sudo_provider = none + +id_provider = ldap +chpass_provider = ldap ldap_uri = ldaps://{{ ldap_server[0] }} ldap_search_base = {{ ldap_basedn }} ldap_schema = rfc2307bis @@ -25,4 +25,11 @@ ldap_sasl_mech = EXTERNAL ldap_tls_cacert = {{ tls_bundle }} ldap_tls_cert = {{ tls_certs }}/{{ inventory_hostname }}.crt ldap_tls_key = {{ tls_private }}/{{ inventory_hostname }}.key + +auth_provider = krb5 krb5_realm = {{ kerberos_realm }} +{% if sssd_allow_groups is defined %} + +access_provider = simple +simple_allow_groups = {{ sssd_allow_groups | join(',') }} +{% endif %} diff --git a/roles/syslogd/tasks/main.yml b/roles/syslogd/tasks/main.yml index 498d76c..cd005bc 100644 --- a/roles/syslogd/tasks/main.yml +++ b/roles/syslogd/tasks/main.yml @@ -8,7 +8,7 @@ ansible.builtin.file: path: /var/log/all.log state: touch - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" when: not result.stat.exists @@ -24,7 +24,7 @@ path: /etc/newsyslog.conf regexp: "^/var/log/all.log.*" line: |- - /var/log/all.log root:{{ ansible_wheel }} 640 7 * $D0 Z + /var/log/all.log root:{{ ansible_wheel }} 640 7 * $D0 Z - name: Configure certificates for remote logging ansible.builtin.service: diff --git a/roles/syslogd/tasks/server.yml b/roles/syslogd/tasks/server.yml index 2f8f90f..cfd8e92 100644 --- a/roles/syslogd/tasks/server.yml +++ b/roles/syslogd/tasks/server.yml @@ -3,7 +3,7 @@ ansible.builtin.file: dest: "{{ item }}" state: directory - mode: 0750 + mode: "0750" owner: root group: "{{ ansible_wheel }}" with_items: @@ -22,7 +22,7 @@ ansible.builtin.copy: dest: "{{ tls_private }}/0.0.0.0:6514.key" src: /srv/letsencrypt/live/loghost.foo.sh/privkey.pem - mode: 0600 + mode: "0600" owner: root group: "{{ ansible_wheel }}" notify: Restart syslogd @@ -32,7 +32,7 @@ ansible.builtin.copy: dest: "{{ tls_certs }}/0.0.0.0:6514.crt" src: /srv/letsencrypt/live/loghost.foo.sh/fullchain.pem - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" notify: Restart syslogd @@ -46,7 +46,7 @@ # everything goes to archive *.* /srv/log/all.log # only local goes to the standard logs - +{{ inventory_hostname }} + +{{ ansible_hostname }} marker: "# {mark} ANSIBLE MANAGED BLOCK (syslogd)" notify: Restart syslogd @@ -59,7 +59,7 @@ ansible.builtin.copy: dest: /usr/local/sbin/syslog-archive src: syslog-archive.sh - mode: 0755 + mode: "0755" owner: root group: "{{ ansible_wheel }}" diff --git a/roles/systemd_resolved/files/resolved.conf b/roles/systemd_resolved/files/resolved.conf new file mode 100644 index 0000000..e4d2629 --- /dev/null +++ b/roles/systemd_resolved/files/resolved.conf @@ -0,0 +1,2 @@ +[global-dns-domain-*] +servers=127.0.0.53 diff --git a/roles/systemd_resolved/handlers/main.yml b/roles/systemd_resolved/handlers/main.yml new file mode 100644 index 0000000..dd37621 --- /dev/null +++ b/roles/systemd_resolved/handlers/main.yml @@ -0,0 +1,10 @@ +--- +- name: Restart systemd-resolved + ansible.builtin.service: + name: systemd-resolved + state: restarted + +- name: Restart NetworkManager + ansible.builtin.service: + name: NetworkManager + state: restarted diff --git a/roles/systemd_resolved/tasks/main.yml b/roles/systemd_resolved/tasks/main.yml new file mode 100644 index 0000000..bb690d6 --- /dev/null +++ b/roles/systemd_resolved/tasks/main.yml @@ -0,0 +1,37 @@ +--- +- name: Install packages + ansible.builtin.package: + name: systemd-resolved + state: installed + +- name: Create config directory + ansible.builtin.file: + path: /etc/systemd/resolved.conf.d + state: directory + mode: "0755" + owner: root + group: "{{ ansible_wheel }}" + +- name: Create config + ansible.builtin.template: + dest: /etc/systemd/resolved.conf.d/local.conf + src: local.conf.j2 + mode: "0644" + owner: root + group: "{{ ansible_wheel }}" + notify: Restart systemd-resolved + +- name: Do not use connection specific DNS servers + ansible.builtin.copy: + dest: /etc/NetworkManager/conf.d/resolved.conf + src: resolved.conf + mode: "0644" + owner: root + group: "{{ ansible_wheel }}" + notify: Restart NetworkManager + +- name: Enable service + ansible.builtin.service: + name: systemd-resolved + state: started + enabled: true diff --git a/roles/systemd_resolved/templates/local.conf.j2 b/roles/systemd_resolved/templates/local.conf.j2 new file mode 100644 index 0000000..7d8e03d --- /dev/null +++ b/roles/systemd_resolved/templates/local.conf.j2 @@ -0,0 +1,4 @@ +[Resolve] +DNS={% for addr in network_dns_servers %}{{ addr }}#{{ lookup('community.general.dig', addr + '/PTR')[:-1] }} {% endfor %} + +DNSOverTLS=yes diff --git a/roles/telegraf/tasks/main.yml b/roles/telegraf/tasks/main.yml index 068f1a4..d1ab303 100644 --- a/roles/telegraf/tasks/main.yml +++ b/roles/telegraf/tasks/main.yml @@ -1,15 +1,19 @@ --- +- name: Add telegraf to hostkey group + ansible.builtin.user: + name: _telegraf + groups: hostkey - name: Install packages ansible.builtin.package: name: telegraf state: installed -- name: Copy config - ansible.builtin.copy: +- name: Create config + ansible.builtin.template: dest: /etc/telegraf/telegraf.conf - src: "{{ ansible_private }}/files/telegraf/telegraf.conf" - mode: 0640 + src: telegraf.conf.j2 + mode: "0640" owner: root group: _telegraf notify: Restart telegraf diff --git a/roles/telegraf/templates/telegraf.conf.j2 b/roles/telegraf/templates/telegraf.conf.j2 new file mode 100644 index 0000000..07b71ba --- /dev/null +++ b/roles/telegraf/templates/telegraf.conf.j2 @@ -0,0 +1,36 @@ +[[outputs.influxdb_v2]] + urls = ["https://influxdb.foo.sh:443"] + token = "{{ influxdb_token }}" + organization = "foo.sh" + bucket = "sensordata" + +[[inputs.mqtt_consumer]] + servers = ["ssl://{{ inventory_hostname }}:8883"] + tls_ca = "{{ tls_certs }}/ca.crt" + tls_cert = "{{ tls_certs }}/{{ inventory_hostname }}.crt" + tls_key = "{{ tls_private }}/{{ inventory_hostname }}.key" + topics = [ + "+/+/+/power", + "+/+/+/temperature", + "+/+/+/sensor/battery", + "+/+/+/sensor/lux", + "+/+/+/sensor/state", + "+/+/+/sensor/temperature", + ] + data_type = "float" + data_format = "value" + + [[inputs.mqtt_consumer.topic_parsing]] + topic = "+/+/+/power" + tags = "location/room/device/_" + measurement = "_/_/_/power" + + [[inputs.mqtt_consumer.topic_parsing]] + topic = "+/+/+/temperature" + tags = "location/room/device/_" + measurement = "_/_/_/temperature" + + [[inputs.mqtt_consumer.topic_parsing]] + topic = "+/+/+/sensor/+" + tags = "location/room/device/_/_" + measurement = "_/_/_/_/measurement" diff --git a/roles/tftp/tasks/main.yml b/roles/tftp/tasks/main.yml index b943c63..bae19d9 100644 --- a/roles/tftp/tasks/main.yml +++ b/roles/tftp/tasks/main.yml @@ -34,7 +34,7 @@ ansible.builtin.file: path: /export/tftpboot state: directory - mode: 0755 + mode: "0755" owner: root group: "{{ ansible_wheel }}" @@ -51,7 +51,7 @@ ansible.builtin.file: path: /etc/systemd/system/tftp.service.d state: directory - mode: 0755 + mode: "0755" owner: root group: "{{ ansible_wheel }}" when: ansible_service_mgr == "systemd" @@ -63,7 +63,7 @@ [Service] ExecStart= ExecStart=/usr/sbin/in.tftpd -s /srv/tftpboot -u tftpd -c -v - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" notify: Restart tftpd diff --git a/roles/mirror/thinlinc/files/sync-thinlinc-repo b/roles/thinlinc_mirror/files/sync-thinlinc-repo.sh similarity index 57% rename from roles/mirror/thinlinc/files/sync-thinlinc-repo rename to roles/thinlinc_mirror/files/sync-thinlinc-repo.sh index 2638197..f510f8f 100755 --- a/roles/mirror/thinlinc/files/sync-thinlinc-repo +++ b/roles/thinlinc_mirror/files/sync-thinlinc-repo.sh @@ -1,4 +1,6 @@ -#!/bin/bash +#!/bin/sh + +set -eu umask 022 @@ -16,8 +18,8 @@ if [ ! -d "${REPODIR}" ]; then mkdir "${REPODIR}" fi -LOCATION=$(curl -s "${BASEURL}/thinlinc/download" | \ - sed -n 's/^.*64-bit.*/\1/p') +LOCATION=$(curl -sf "${BASEURL}/thinlinc/download/" | \ + sed -n 's/^.*&2 exit 1 @@ -25,23 +27,26 @@ fi PKGNAME="$(basename "${LOCATION}")" if [ ! -f "${REPODIR}/${PKGNAME}" ]; then - echo "New thinlinc version found" + VERSION="$(echo "$PKGNAME" | sed -n 's/^thinlinc-client-\([0-9\.]*\)-[0-9]*\.x86_64\.rpm/\1/p')" + + echo "New thinlinc version ${VERSION} found" echo "" + tmpfile="$(mktemp)" + trap 'rm -f "$tmpfile"' EXIT + # assume that server version goes in-line with client echo "Downloading server package:" - curl -so "${REPODIR}/.server.zip" "${BASEURL}/downloads/server/download.py" + curl -sfo "$tmpfile" "${BASEURL}/downloads/server/tl-${VERSION}-server.zip" echo "Extracting server rpm files:" - unzip -jd ${REPODIR} ${REPODIR}/.server.zip \*.rpm - echo "Cleaning up..." - rm -f ${REPODIR}/.server.zip - echo "" + unzip -jd "$REPODIR" "$tmpfile" \*.rpm echo "Downloading client rpm package:" - curl -so "${REPODIR}/${PKGNAME}" "${BASEURL}${LOCATION}" + curl -sfo "${REPODIR}/${PKGNAME}" "${LOCATION}" echo "" echo "Updating repository metadata:" createrepo_c "${REPODIR}" echo "" -fi + unzip -p "$tmpfile" "*release-notes-*.txt" +fi diff --git a/roles/mirror/thinlinc/tasks/main.yml b/roles/thinlinc_mirror/tasks/main.yml similarity index 92% rename from roles/mirror/thinlinc/tasks/main.yml rename to roles/thinlinc_mirror/tasks/main.yml index 4a7f785..2fb0edc 100644 --- a/roles/mirror/thinlinc/tasks/main.yml +++ b/roles/thinlinc_mirror/tasks/main.yml @@ -11,7 +11,7 @@ ansible.builtin.file: path: /srv/mirrors/thinlinc state: directory - mode: 0755 + mode: "0755" owner: mirror group: mirror @@ -27,8 +27,8 @@ - name: Copy sync script ansible.builtin.copy: dest: /usr/local/bin/sync-thinlinc-repo - src: sync-thinlinc-repo - mode: 0755 + src: sync-thinlinc-repo.sh + mode: "0755" owner: root group: root diff --git a/roles/thinlinc_server/files/tl-setup.local.sh b/roles/thinlinc_server/files/tl-setup.local.sh index c657426..acd3b39 100755 --- a/roles/thinlinc_server/files/tl-setup.local.sh +++ b/roles/thinlinc_server/files/tl-setup.local.sh @@ -1,22 +1,26 @@ #!/bin/sh +set -eu + cat < /root/tl-setup.answer -install-pygtk=yes -email-address=adm@foo.sh -setup-selinux=yes -setup-nearest=no -server-type=master -setup-firewall=no -install-python-ldap=no -setup-apparmor=no -missing-answer=ask -install-nfs=no -setup-thinlocal=no -install-sshd=no -tlwebadm-password=$(dd if=/dev/urandom count=1 2> /dev/null | base64 | tail -n 1 | cut -c 1-20) accept-eula=yes +server-type=master migrate-conf=old install-required-libs=yes +install-nfs=no +install-sshd=no +install-gtk=yes +install-python-ldap=no +agent-hostname-choice=manual +manual-agent-hostname=$(hostname -f) +email-address=adm@foo.sh +tlwebadm-password=$(dd if=/dev/urandom count=1 2> /dev/null | base64 | tail -n 1 | cut -c 1-20) +setup-thinlocal=no +setup-nearest=no +setup-firewall=no +setup-selinux=yes +setup-apparmor=no +missing-answer=abort EOF /opt/thinlinc/sbin/tl-setup -a /root/tl-setup.answer diff --git a/roles/thinlinc_server/tasks/main.yml b/roles/thinlinc_server/tasks/main.yml index 554e527..19eca7e 100644 --- a/roles/thinlinc_server/tasks/main.yml +++ b/roles/thinlinc_server/tasks/main.yml @@ -5,6 +5,7 @@ state: installed with_items: - gtk3 + - librsvg2 - polkit - python3 - python3-gobject @@ -19,16 +20,8 @@ - name: Install packages ansible.builtin.package: - name: "{{ item }}" + name: "thinlinc-server" state: installed - with_items: - - thinlinc-tladm - - thinlinc-tlmisc - - thinlinc-tlmisc-libs - - thinlinc-tlprinter - - thinlinc-vnc-server - - thinlinc-vsm - - thinlinc-webaccess - name: Run ThinLinc setup ansible.builtin.script: @@ -39,7 +32,7 @@ ansible.builtin.copy: dest: /etc/polkit-1/rules.d/40-thinlinc-no-auth-dialogs.rules src: 40-thinlinc-no-auth-dialogs.rules - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" @@ -55,18 +48,11 @@ regexp: "^show_intro=.*" line: show_intro=false -- name: Configure vsmagent hostname - ansible.builtin.lineinfile: - path: /opt/thinlinc/etc/conf.d/vsmagent.hconf - regexp: "^agent_hostname=.*" - line: "agent_hostname={{ inventory_hostname }}" - notify: Restart vsmagent - - name: Copy private key ansible.builtin.copy: dest: /opt/thinlinc/etc/tlwebaccess/server.key src: "{{ item }}" - mode: 0600 + mode: "0600" owner: root group: "{{ ansible_wheel }}" with_first_found: @@ -79,7 +65,7 @@ ansible.builtin.copy: dest: /opt/thinlinc/etc/tlwebaccess/server.crt src: "{{ item }}" - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" validate: /usr/bin/openssl x509 -in %s -noout diff --git a/roles/gitea/handlers/main.yml b/roles/tlshd/handlers/main.yml similarity index 57% rename from roles/gitea/handlers/main.yml rename to roles/tlshd/handlers/main.yml index a8e19c4..ed0f6fd 100644 --- a/roles/gitea/handlers/main.yml +++ b/roles/tlshd/handlers/main.yml @@ -1,5 +1,5 @@ --- -- name: Restart gitea +- name: Restart tlshd ansible.builtin.service: - name: gitea + name: tlshd state: restarted diff --git a/roles/tlshd/tasks/main.yml b/roles/tlshd/tasks/main.yml new file mode 100644 index 0000000..7105884 --- /dev/null +++ b/roles/tlshd/tasks/main.yml @@ -0,0 +1,30 @@ +--- +- name: Install packages + ansible.builtin.package: + name: ktls-utils + +- name: Configure tlshd + ansible.builtin.template: + dest: /etc/tlshd.conf + src: tlshd.conf.j2 + mode: "0644" + owner: root + group: "{{ ansible_wheel }}" + notify: Restart tlshd + +- name: Configure tlshd private key + ansible.builtin.copy: + dest: "{{ tls_private }}/tlshd.key" + src: "{{ tls_private }}/{{ inventory_hostname }}.key" + mode: "0600" + owner: root + group: "{{ ansible_wheel }}" + remote_src: true + tags: certificates + notify: Restart tlshd + +- name: Enable tlshd services + ansible.builtin.service: + name: tlshd + state: started + enabled: true diff --git a/roles/tlshd/templates/tlshd.conf.j2 b/roles/tlshd/templates/tlshd.conf.j2 new file mode 100644 index 0000000..5063216 --- /dev/null +++ b/roles/tlshd/templates/tlshd.conf.j2 @@ -0,0 +1,16 @@ +[debug] +loglevel=0 +tls=0 +nl=0 + +[authenticate] + +[authenticate.client] +x509.truststore = {{ tls_certs }}/ca.crt +x509.certificate = {{ tls_certs }}/{{ inventory_hostname }}.crt +x509.private_key = {{ tls_private }}/tlshd.key + +[authenticate.server] +x509.truststore = {{ tls_certs }}/ca.crt +x509.certificate = {{ tls_certs }}/{{ inventory_hostname }}.crt +x509.private_key = {{ tls_private }}/tlshd.key diff --git a/roles/udev/handlers/main.yml b/roles/udev/handlers/main.yml new file mode 100644 index 0000000..46fb293 --- /dev/null +++ b/roles/udev/handlers/main.yml @@ -0,0 +1,14 @@ +--- +- name: Reload udev rules + ansible.builtin.command: + argv: + - udevadm + - control + - --reload-rules + notify: Trigger udev rules + +- name: Trigger udev rules + ansible.builtin.command: + argv: + - udevadm + - trigger diff --git a/roles/unbound/tasks/main.yml b/roles/unbound/tasks/main.yml index 1f6699a..a64720b 100644 --- a/roles/unbound/tasks/main.yml +++ b/roles/unbound/tasks/main.yml @@ -12,14 +12,25 @@ ansible.builtin.command: argv: - unbound-control-setup - creates: "{{ unbound_control_key }}" + creates: "{{ unbound_confdir }}/unbound_control.key" notify: Restart unbound +- name: Copy zone files + ansible.builtin.copy: + dest: "{{ unbound_zonedir }}/{{ item }}" + src: "/srv/dns/{{ item }}" + mode: "0644" + owner: root + group: "{{ ansible_wheel }}" + with_items: "{{ unbound_zones }}" + notify: Restart unbound + when: unbound_zones is defined + - name: Copy config ansible.builtin.template: - dest: "{{ unbound_conf }}" + dest: "{{ unbound_confdir }}/unbound.conf" src: "unbound.conf.{{ inventory_hostname }}.j2" - mode: 0644 + mode: "0644" owner: root group: "{{ ansible_wheel }}" validate: "unbound-checkconf %s" diff --git a/roles/unbound/templates/unbound.conf.dna-gw01.home.foo.sh.j2 b/roles/unbound/templates/unbound.conf.dna-gw01.home.foo.sh.j2 index 7977574..4765817 100644 --- a/roles/unbound/templates/unbound.conf.dna-gw01.home.foo.sh.j2 +++ b/roles/unbound/templates/unbound.conf.dna-gw01.home.foo.sh.j2 @@ -1,14 +1,22 @@ - server: - interface: 127.0.0.1 - interface: ::1 + # https://nlnetlabs.nl/documentation/unbound/howto-optimise/ + num-threads: {{ ansible_processor_cores }} + msg-cache-slabs: {{ ansible_processor_cores | int | pow(2) | int }} + rrset-cache-slabs: {{ ansible_processor_cores | int | pow(2) | int }} + infra-cache-slabs: {{ ansible_processor_cores | int | pow(2) | int }} + key-cache-slabs: {{ ansible_processor_cores | int | pow(2) | int }} + interface: 172.20.20.10@53 interface: 172.20.20.10@853 + interface: 172.20.20.11@53 + interface: 172.20.20.11@853 + interface: 172.20.20.12@53 + interface: 172.20.20.12@853 interface: 172.20.21.1@53 tls-service-key: {{ tls_private }}/dns.home.foo.sh.key tls-service-pem: {{ tls_certs }}/dns.home.foo.sh.crt - tls-cert-bundle: {{ tls_certs }}/ca.crt + tls-cert-bundle: {{ tls_bundle }} access-control: 127.0.0.0/8 allow access-control: ::1 allow @@ -26,9 +34,14 @@ remote-control: control-enable: yes control-interface: /var/run/unbound.sock +forward-zone: + name: "." + forward-tls-upstream: yes + forward-addr: 8.8.8.8@853#dns.google + forward-addr: 8.8.4.4@853#dns.google + +{% for zone in unbound_zones %} auth-zone: - name: "home.foo.sh" - zonefile: "/var/unbound/db/home.foo.sh" -auth-zone: - name: "20.172.in-addr.arpa" - zonefile: "/var/unbound/db/20.172.in-addr.arpa" + name: "{{ zone }}" + zonefile: "{{ unbound_zonedir }}/{{ zone }}" +{% endfor %} diff --git a/roles/unbound/templates/unbound.conf.dna-gw02.home.foo.sh.j2 b/roles/unbound/templates/unbound.conf.dna-gw02.home.foo.sh.j2 index c7090c2..c08d855 100644 --- a/roles/unbound/templates/unbound.conf.dna-gw02.home.foo.sh.j2 +++ b/roles/unbound/templates/unbound.conf.dna-gw02.home.foo.sh.j2 @@ -1,14 +1,22 @@ - server: - interface: 127.0.0.1 - interface: ::1 + # https://nlnetlabs.nl/documentation/unbound/howto-optimise/ + num-threads: {{ ansible_processor_cores }} + msg-cache-slabs: {{ ansible_processor_cores | int | pow(2) | int }} + rrset-cache-slabs: {{ ansible_processor_cores | int | pow(2) | int }} + infra-cache-slabs: {{ ansible_processor_cores | int | pow(2) | int }} + key-cache-slabs: {{ ansible_processor_cores | int | pow(2) | int }} + interface: 172.20.20.10@53 interface: 172.20.20.10@853 + interface: 172.20.20.11@53 + interface: 172.20.20.11@853 + interface: 172.20.20.12@53 + interface: 172.20.20.12@853 interface: 172.20.21.2@53 tls-service-key: {{ tls_private }}/dns.home.foo.sh.key tls-service-pem: {{ tls_certs }}/dns.home.foo.sh.crt - tls-cert-bundle: {{ tls_certs }}/ca.crt + tls-cert-bundle: {{ tls_bundle }} access-control: 127.0.0.0/8 allow access-control: ::1 allow @@ -26,9 +34,14 @@ remote-control: control-enable: yes control-interface: /var/run/unbound.sock +forward-zone: + name: "." + forward-tls-upstream: yes + forward-addr: 8.8.8.8@853#dns.google + forward-addr: 8.8.4.4@853#dns.google + +{% for zone in unbound_zones %} auth-zone: - name: "home.foo.sh" - zonefile: "/var/unbound/db/home.foo.sh" -auth-zone: - name: "20.172.in-addr.arpa" - zonefile: "/var/unbound/db/20.172.in-addr.arpa" + name: "{{ zone }}" + zonefile: "{{ unbound_zonedir }}/{{ zone }}" +{% endfor %} diff --git a/roles/unbound/templates/unbound.conf.zm02.home.foo.sh.j2 b/roles/unbound/templates/unbound.conf.frigate02.home.foo.sh.j2 similarity index 74% rename from roles/unbound/templates/unbound.conf.zm02.home.foo.sh.j2 rename to roles/unbound/templates/unbound.conf.frigate02.home.foo.sh.j2 index a4d3f59..3f51925 100644 --- a/roles/unbound/templates/unbound.conf.zm02.home.foo.sh.j2 +++ b/roles/unbound/templates/unbound.conf.frigate02.home.foo.sh.j2 @@ -29,10 +29,11 @@ remote-control: forward-zone: name: "." forward-addr: 172.20.20.10@853#dns.home.foo.sh + forward-addr: 172.20.20.11@853#dns.home.foo.sh + forward-addr: 172.20.20.12@853#dns.home.foo.sh +{% for zone in unbound_zones %} auth-zone: - name: "cam.foo.sh" - zonefile: "/var/lib/unbound/cam.foo.sh" -auth-zone: - name: "26.20.172.in-addr.arpa" - zonefile: "/var/lib/unbound/26.20.172.in-addr.arpa" + name: "{{ zone }}" + zonefile: "{{ unbound_zonedir }}/{{ zone }}" +{% endfor %} diff --git a/roles/unbound/templates/unbound.conf.nms01.home.foo.sh.j2 b/roles/unbound/templates/unbound.conf.nms01.home.foo.sh.j2 index a842fcd..c29a61c 100644 --- a/roles/unbound/templates/unbound.conf.nms01.home.foo.sh.j2 +++ b/roles/unbound/templates/unbound.conf.nms01.home.foo.sh.j2 @@ -29,10 +29,11 @@ remote-control: forward-zone: name: "." forward-addr: 172.20.20.10@853#dns.home.foo.sh + forward-addr: 172.20.20.11@853#dns.home.foo.sh + forward-addr: 172.20.20.12@853#dns.home.foo.sh +{% for zone in unbound_zones %} auth-zone: - name: "oob.foo.sh" - zonefile: "/var/lib/unbound/oob.foo.sh" -auth-zone: - name: "25.20.172.in-addr.arpa" - zonefile: "/var/lib/unbound/25.20.172.in-addr.arpa" + name: "{{ zone }}" + zonefile: "{{ unbound_zonedir }}/{{ zone }}" +{% endfor %} diff --git a/roles/unbound/templates/unbound.conf.print01.home.foo.sh.j2 b/roles/unbound/templates/unbound.conf.print01.home.foo.sh.j2 index 4799b50..481064f 100644 --- a/roles/unbound/templates/unbound.conf.print01.home.foo.sh.j2 +++ b/roles/unbound/templates/unbound.conf.print01.home.foo.sh.j2 @@ -29,10 +29,11 @@ remote-control: forward-zone: name: "." forward-addr: 172.20.20.10@853#dns.home.foo.sh + forward-addr: 172.20.20.11@853#dns.home.foo.sh + forward-addr: 172.20.20.12@853#dns.home.foo.sh +{% for zone in unbound_zones %} auth-zone: - name: "print.foo.sh" - zonefile: "/var/lib/unbound/print.foo.sh" -auth-zone: - name: "24.20.172.in-addr.arpa" - zonefile: "/var/lib/unbound/24.20.172.in-addr.arpa" + name: "{{ zone }}" + zonefile: "{{ unbound_zonedir }}/{{ zone }}" +{% endfor %} diff --git a/roles/unbound/vars/OpenBSD.yml b/roles/unbound/vars/OpenBSD.yml index 4ce4313..5f41acd 100644 --- a/roles/unbound/vars/OpenBSD.yml +++ b/roles/unbound/vars/OpenBSD.yml @@ -1,3 +1,4 @@ --- -unbound_conf: /var/unbound/etc/unbound.conf -unbound_control_key: /var/unbound/etc/unbound_control.key +unbound_chroot: /var/unbound +unbound_confdir: "{{ unbound_chroot }}/etc" +unbound_zonedir: "{{ unbound_chroot }}/db" diff --git a/roles/unbound/vars/RedHat.yml b/roles/unbound/vars/RedHat.yml index 48bfadd..816739c 100644 --- a/roles/unbound/vars/RedHat.yml +++ b/roles/unbound/vars/RedHat.yml @@ -1,3 +1,3 @@ --- -unbound_conf: /etc/unbound/unbound.conf -unbound_control_key: /etc/unbound/unbound_control.key +unbound_confdir: /etc/unbound +unbound_zonedir: /var/lib/unbound diff --git a/roles/unbound_exporter/files/unbound_exporter_stunnel.sh b/roles/unbound_exporter/files/unbound_exporter_stunnel.sh new file mode 100755 index 0000000..8328224 --- /dev/null +++ b/roles/unbound_exporter/files/unbound_exporter_stunnel.sh @@ -0,0 +1,10 @@ +#!/bin/ksh + +daemon="/usr/local/sbin/stunnel" +daemon_flags="/etc/unbound_exporter/stunnel.conf" + +. /etc/rc.d/rc.subr + +rc_reload=NO + +rc_cmd $1 diff --git a/roles/unbound_exporter/handlers/main.yml b/roles/unbound_exporter/handlers/main.yml new file mode 100644 index 0000000..2cd8d99 --- /dev/null +++ b/roles/unbound_exporter/handlers/main.yml @@ -0,0 +1,10 @@ +--- +- name: Restart unbound_exporter + ansible.builtin.service: + name: unbound_exporter + state: restarted + +- name: Restart unbound_exporter_stunnel + ansible.builtin.service: + name: unbound_exporter_stunnel + state: restarted diff --git a/roles/unbound_exporter/tasks/main.yml b/roles/unbound_exporter/tasks/main.yml new file mode 100644 index 0000000..b194422 --- /dev/null +++ b/roles/unbound_exporter/tasks/main.yml @@ -0,0 +1,60 @@ +--- +- name: Install packages + ansible.builtin.package: + name: "{{ item }}" + state: installed + with_items: + - stunnel + - unbound_exporter + +- name: Add user to hostkey group + ansible.builtin.user: + name: _unboundexporter + groups: hostkey + append: true + create_home: false + notify: Restart unbound_exporter_stunnel + +- name: Create config directory + ansible.builtin.file: + path: /etc/unbound_exporter + state: directory + mode: "0755" + owner: root + group: "{{ ansible_wheel }}" + +- name: Create stunnel config + ansible.builtin.template: + dest: /etc/unbound_exporter/stunnel.conf + src: stunnel.conf.j2 + mode: "0644" + owner: root + group: "{{ ansible_wheel }}" + notify: Restart unbound_exporter_stunnel + +- name: Enable service + ansible.builtin.service: + name: unbound_exporter + state: started + enabled: true + arguments: >- + -unbound.ca + -unbound.cert + -unbound.host unix:///var/run/unbound.sock + -web.listen-address 127.0.0.1:9167 + notify: Restart unbound_exporter + +- name: Create stunnel service config + ansible.builtin.copy: + dest: /etc/rc.d/unbound_exporter_stunnel + src: unbound_exporter_stunnel.sh + mode: "0755" + owner: root + group: "{{ ansible_wheel }}" + notify: Restart unbound_exporter_stunnel + +- name: Enable stunnel service + ansible.builtin.service: + name: unbound_exporter_stunnel + state: started + enabled: true diff --git a/roles/unbound_exporter/templates/stunnel.conf.j2 b/roles/unbound_exporter/templates/stunnel.conf.j2 new file mode 100644 index 0000000..8f4aab4 --- /dev/null +++ b/roles/unbound_exporter/templates/stunnel.conf.j2 @@ -0,0 +1,23 @@ +setuid = _unboundexporter +setgid = _unboundexporter + +sslVersionMin = TLSv1.3 +ciphersuites = TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256 +curves = X25519:prime256v1:secp384r1 + +key = {{ tls_private }}/{{ inventory_hostname }}.key +cert = {{ tls_certs }}/{{ inventory_hostname }}.crt + +verify = 2 +CAfile = {{ tls_certs }}/ca.crt + +syslog = yes + +[unbound_exporter] +{% for ip in ansible_all_ipv4_addresses %} +accept = {{ ip }}:9167 +{% endfor %} +connect = 127.0.0.1:9167 +{% for host in groups['prometheus'] %} +checkHost = {{ host }} +{% endfor %} diff --git a/roles/unwind/handlers/main.yml b/roles/unwind/handlers/main.yml new file mode 100644 index 0000000..05d7492 --- /dev/null +++ b/roles/unwind/handlers/main.yml @@ -0,0 +1,5 @@ +--- +- name: Restart unwind + ansible.builtin.service: + name: unwind + state: restarted diff --git a/roles/unwind/tasks/main.yml b/roles/unwind/tasks/main.yml new file mode 100644 index 0000000..99dd212 --- /dev/null +++ b/roles/unwind/tasks/main.yml @@ -0,0 +1,16 @@ +--- +- name: Copy config + ansible.builtin.template: + dest: /etc/unwind.conf + src: unwind.conf.j2 + mode: "0644" + owner: root + group: "{{ ansible_wheel }}" + validate: "unwind -n -f %s" + notify: Restart unwind + +- name: Enable service + ansible.builtin.service: + name: unwind + state: started + enabled: true diff --git a/roles/unwind/templates/unwind.conf.j2 b/roles/unwind/templates/unwind.conf.j2 new file mode 100644 index 0000000..2a704ce --- /dev/null +++ b/roles/unwind/templates/unwind.conf.j2 @@ -0,0 +1,10 @@ +{% if network_dns_servers is defined %} +forwarder { +{% for addr in network_dns_servers %} + {{ addr }} port 853 authentication name "{{ lookup('community.general.dig', addr + '/PTR')[:-1] }}" DoT +{% endfor %} +} +preference { DoT } +{% else %} +preference { oDoT-autoconf } +{% endif %} diff --git a/roles/web_build/tasks/main.yml b/roles/web_build/tasks/main.yml index 6fb8ba2..d2aed36 100644 --- a/roles/web_build/tasks/main.yml +++ b/roles/web_build/tasks/main.yml @@ -3,7 +3,7 @@ ansible.builtin.file: path: /export/web-build state: directory - mode: 0755 + mode: "0755" owner: root group: "{{ ansible_wheel }}" @@ -20,6 +20,6 @@ ansible.builtin.copy: dest: /usr/local/bin/web-sync src: web-sync.sh - mode: 0755 + mode: "0755" owner: root group: "{{ ansible_wheel }}" diff --git a/roles/web_logs/files/combine-logs.py b/roles/web_logs/files/combine-logs.py new file mode 100644 index 0000000..e7044fa --- /dev/null +++ b/roles/web_logs/files/combine-logs.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python3 + +import argparse +import datetime +import os +import sys + +from time import mktime + + +def read_line(log, date=None): + while True: + line = log["fp"].readline().strip() + if not line: + raise EOFError + time = datetime.datetime.strptime( + " ".join(line.split()[3:5]), "[%d/%b/%Y:%H:%M:%S +0000]" + ) + if date is not None and time.strftime("%Y-%m-%d") != date: + continue + log["time"] = time + log["line"] = line + log["linenum"] += 1 + break + + +def combine_logs(logfiles, date=None): + logs = [] + for logfile in logfiles: + if os.stat(logfile).st_size == 0: + continue + logs.append( + {"fp": open(logfile, "r"), "line": None, "linenum": 0, "time": None} + ) + try: + read_line(logs[-1], date) + except EOFError: + del logs[-1] + + while True: + if len(logs) == 0: + break + logs = sorted(logs, key=lambda x: x["time"]) + print(logs[0]["line"]) + try: + read_line(logs[0], date) + except EOFError: + del logs[0] + + +def date_now(): + return datetime.datetime.now() + + +if __name__ == "__main__": + try: + parser = argparse.ArgumentParser() + parser.add_argument("-d", "--date", default=None) + parser.add_argument("logfiles", nargs="+") + args = parser.parse_args() + if args.date is not None: + if args.date == "today": + date = date_now().strftime("%Y-%m-%d") + elif args.date == "yesterday": + date = (date_now() - datetime.timedelta(days=1)).strftime("%Y-%m-%d") + else: + date = args.date + combine_logs(args.logfiles, date=date) + except KeyboardInterrupt: + sys.ext(1) diff --git a/roles/web_logs/tasks/main.yml b/roles/web_logs/tasks/main.yml index 04e1c7e..27bf8ab 100644 --- a/roles/web_logs/tasks/main.yml +++ b/roles/web_logs/tasks/main.yml @@ -2,6 +2,7 @@ - name: Create logsync group ansible.builtin.group: name: logsync + gid: 312 system: true - name: Create logsync user @@ -11,72 +12,38 @@ createhome: false group: logsync home: /var/empty - shell: /sbin/nologin + shell: /bin/sh system: true + uid: 312 -- name: Create logsync ssh key directory - ansible.builtin.file: - path: /etc/ssh/logsync - state: directory - mode: 0750 - owner: root - group: logsync - -- name: Create logsync ssh keys - ansible.builtin.command: - argv: - - ssh-keygen - - -t - - ed25519 - - -C - - "logsync@{{ inventory_hostname }}" - - -N - - "" - - -f - - /etc/ssh/logsync/id_ed25519 - creates: /etc/ssh/logsync/id_ed25519 - -- name: Fix logsync ssh key permissions - ansible.builtin.file: - path: "{{ item }}" - owner: root - group: logsync - mode: 0640 - with_items: - - /etc/ssh/logsync/id_ed25519 - - /etc/ssh/logsync/id_ed25519.pub - -- name: Import rclone role - ansible.builtin.import_role: +- name: Include rclone role + ansible.builtin.include_role: name: rclone vars: - local_user: logsync - remote_user: logsync - hostgroup: webservers - destination: /var/cache/sync-http-logs - private_key: /etc/ssh/logsync/id_ed25519 + rclone_hostgroup: proxy + rclone_service: logsync -- name: Create cache directory - ansible.builtin.file: - path: /var/cache/sync-http-logs - state: directory - mode: 0750 - owner: logsync - group: logsync - -- name: Create log directory +- name: Create data directory ansible.builtin.file: path: /export/web-log state: directory - mode: 0750 + mode: "0750" owner: root group: "{{ ansible_wheel }}" - name: Link data directory ansible.builtin.file: - dest: /srv/web-log + path: /srv/web-log src: /export/web-log state: link owner: root group: "{{ ansible_wheel }}" follow: false + +- name: Copy log combiner + ansible.builtin.copy: + dest: /usr/local/bin/combine-logs + src: combine-logs.py + mode: "0755" + owner: root + group: "{{ ansible_wheel }}" diff --git a/roles/web_logs/templates/rclone.conf.j2 b/roles/web_logs/templates/rclone.conf.j2 deleted file mode 100644 index 34524ec..0000000 --- a/roles/web_logs/templates/rclone.conf.j2 +++ /dev/null @@ -1,10 +0,0 @@ -# {{ ansible_managed }} -{% for host in groups['webservers'] %} - -[{{ host.split('.')[0] }}] -type = sftp -host = {{ host }} -user = logsync -key_file = ~/.ssh/id_ed25519 -known_hosts_file = /etc/ssh/ssh_known_hosts -{% endfor %} diff --git a/roles/websockify/tasks/main.yml b/roles/websockify/tasks/main.yml index 27d1ba0..1388e87 100644 --- a/roles/websockify/tasks/main.yml +++ b/roles/websockify/tasks/main.yml @@ -23,7 +23,7 @@ ansible.builtin.template: dest: /etc/websockify.conf src: websockify.conf.j2 - mode: 0640 + mode: "0640" owner: root group: websock notify: Restart websockify @@ -32,7 +32,7 @@ ansible.builtin.copy: dest: /etc/rc.d/websockify src: rc.websockify - mode: 0555 + mode: "0555" owner: root group: "{{ ansible_wheel }}" notify: Restart websockify diff --git a/roles/zoneminder/defaults/main.yml b/roles/zoneminder/defaults/main.yml deleted file mode 100644 index a4bf72a..0000000 --- a/roles/zoneminder/defaults/main.yml +++ /dev/null @@ -1,4 +0,0 @@ ---- -zm_mysql_host: localhost -zm_mysql_db: zm -zm_mysql_user: zmuser diff --git a/roles/zoneminder/tasks/main.yml b/roles/zoneminder/tasks/main.yml deleted file mode 100644 index 8ee40c0..0000000 --- a/roles/zoneminder/tasks/main.yml +++ /dev/null @@ -1,129 +0,0 @@ ---- -- name: Fix SELinux contexts from cache directory - community.general.sefcontext: - path: "/var/cache/zoneminder(/.*)?" - setype: httpd_cache_t - -- name: Install packages - ansible.builtin.package: - name: "{{ item }}" - state: installed - with_items: - - mariadb - - zoneminder-httpd - -- name: Fix SELinux contexts from data directory - community.general.sefcontext: - path: "/export/zoneminder(/.*)?" - setype: zoneminder_var_lib_t - -- name: Create data directory - ansible.builtin.file: - path: /export/zoneminder - state: directory - mode: 0750 - owner: apache - group: apache - setype: _default - -- name: Link data directory - ansible.builtin.file: - dest: /srv/zoneminder - src: /export/zoneminder - state: link - owner: root - group: "{{ ansible_wheel }}" - follow: false - -- name: Create config - ansible.builtin.template: - dest: /etc/zm/conf.d/local.conf - src: zm.conf - mode: 0640 - owner: root - group: apache - notify: Restart zoneminder - -- name: Remove mariadb depency from unit file - ansible.builtin.shell: - cmd: >- - sed -e 's/mariadb\.service//' /lib/systemd/system/zoneminder.service - > /etc/systemd/system/zoneminder.service - creates: /etc/systemd/system/zoneminder.service - warn: false - notify: Restart zoneminder - when: zm_mysql_host != "localhost" - -- name: Allow zoneminder to read host private key - ansible.builtin.user: - name: apache - groups: hostkey - append: true - notify: Restart zoneminder - when: zm_mysql_host != "localhost" - -- name: Loosen SELinux settings - ansible.posix.seboolean: - name: "{{ item }}" - state: true - persistent: true - with_items: - - domain_can_mmap_files - - nis_enabled - -# selinux doesn't allow create this -- name: Create stub web log - ansible.builtin.file: - dest: /var/log/zoneminder/web_php.log - state: touch - mode: 0640 - owner: apache - group: apache - access_time: preserve - modification_time: preserve - -- name: Link apache config - ansible.builtin.file: - dest: /etc/httpd/conf.local.d/zm.conf - src: /etc/zm/www/zoneminder.httpd.conf - state: link - owner: root - group: "{{ ansible_wheel }}" - notify: Restart apache - -- name: Link apache php config - ansible.builtin.file: - dest: /etc/httpd/conf.local.d/php.conf - src: /etc/httpd/conf.d/php.conf - state: link - owner: root - group: "{{ ansible_wheel }}" - notify: Restart apache - -- name: Configure zoneminder timezone - ansible.builtin.copy: - dest: /etc/php.d/timezone.ini - content: "date.timezone=UTC\n" - mode: 0644 - owner: root - group: "{{ ansible_wheel }}" - notify: Restart apache - -# required for database updates to work -- name: Configure mysql client to use ssl - ansible.builtin.copy: - dest: /root/.my.cnf - content: | - [client] - ssl-ca={{ tls_certs }}/ca.crt - ssl-cert={{ tls_certs }}/{{ inventory_hostname }}.crt - ssl-key={{ tls_private }}/{{ inventory_hostname }}.key - mode: 0600 - owner: root - group: "{{ ansible_wheel }}" - -- name: Enable service - ansible.builtin.service: - name: zoneminder - state: started - enabled: true diff --git a/roles/zoneminder/templates/zm.conf b/roles/zoneminder/templates/zm.conf deleted file mode 100644 index 9e29854..0000000 --- a/roles/zoneminder/templates/zm.conf +++ /dev/null @@ -1,13 +0,0 @@ -# {{ ansible_managed }} - -ZM_DIR_EVENTS=/srv/zoneminder - -ZM_DB_HOST={{ zm_mysql_host }} -ZM_DB_NAME={{ zm_mysql_db}} -ZM_DB_USER={{ zm_mysql_user }} -ZM_DB_PASS={{ zm_mysql_pass }} -{% if zm_mysql_host != "localhost" %} -ZM_DB_SSL_CA_CERT={{ tls_certs }}/ca.crt -ZM_DB_SSL_CLIENT_KEY={{ tls_private }}/{{ inventory_hostname }}.key -ZM_DB_SSL_CLIENT_CERT={{ tls_certs }}/{{ inventory_hostname }}.crt -{% endif %} diff --git a/scripts/check-updates b/scripts/check-updates new file mode 100755 index 0000000..5a00e56 --- /dev/null +++ b/scripts/check-updates @@ -0,0 +1,16 @@ +#!/bin/sh + +set -eu + +if [ $# -eq 1 ]; then + limit="$1" +elif [ $# -ne 0 ]; then + echo "Usage: $(basename "$0") [hostname]" 1>&2 + exit 1 +else + limit="all" +fi + +cd "$(dirname "$0")/.." + +ansible-playbook playbooks/manual/check-updates.yml -l "$limit" diff --git a/site.yml b/site.yml index 41765a2..bee03dd 100644 --- a/site.yml +++ b/site.yml @@ -1,18 +1,20 @@ --- - name: Configure adm hosts ansible.builtin.import_playbook: playbooks/adm.yml +- name: Configure audiobooks hosts + ansible.builtin.import_playbook: playbooks/audiobooks.yml - name: Configure backup hosts ansible.builtin.import_playbook: playbooks/backup.yml - name: Configure collab hosts ansible.builtin.import_playbook: playbooks/collab.yml - name: Configure dna-gw hosts ansible.builtin.import_playbook: playbooks/dna-gw.yml +- name: Configure forgejo hosts + ansible.builtin.import_playbook: playbooks/forgejo.yml +- name: Configure frigate hosts + ansible.builtin.import_playbook: playbooks/frigate.yml - name: Configure fsol-gw hosts ansible.builtin.import_playbook: playbooks/fsol-gw.yml -- name: Configure gitea-runner hosts - ansible.builtin.import_playbook: playbooks/gitea-runner.yml -- name: Configure gitea hosts - ansible.builtin.import_playbook: playbooks/gitea.yml - name: Configure homeassistant hosts ansible.builtin.import_playbook: playbooks/homeassistant.yml - name: Configure influxdb hosts @@ -41,10 +43,14 @@ ansible.builtin.import_playbook: playbooks/oci-node.yml - name: Configure print hosts ansible.builtin.import_playbook: playbooks/print.yml +- name: Configure prometheus hosts + ansible.builtin.import_playbook: playbooks/prometheus.yml - name: Configure proxy hosts ansible.builtin.import_playbook: playbooks/proxy.yml - name: Configure relay hosts ansible.builtin.import_playbook: playbooks/relay.yml +- name: Configure sane hosts + ansible.builtin.import_playbook: playbooks/sane.yml - name: Configure shell hosts ansible.builtin.import_playbook: playbooks/shell.yml - name: Configure sqldb hosts @@ -53,5 +59,3 @@ ansible.builtin.import_playbook: playbooks/static.yml - name: Configure vmhost hosts ansible.builtin.import_playbook: playbooks/vmhost.yml -- name: Configure zm hosts - ansible.builtin.import_playbook: playbooks/zm.yml diff --git a/software b/software index 225d79a..b9a2d06 160000 --- a/software +++ b/software @@ -1 +1 @@ -Subproject commit 225d79acad76f0becbd4db481abc7a8039014a8c +Subproject commit b9a2d06df00afafcc47403cc5334c64c7fa2f594 diff --git a/tests/03-shellcheck.sh b/tests/11-shellcheck.sh similarity index 100% rename from tests/03-shellcheck.sh rename to tests/11-shellcheck.sh diff --git a/user.list b/user.list deleted file mode 100644 index 3fc5a6d..0000000 --- a/user.list +++ /dev/null @@ -1,17 +0,0 @@ - -This file lists all users and groups that have reserved uid/gid and are -created using ansible rules. If a user/group pair is created, they share -the same uid/gid. If a user is member of a system group, leave the group -entry empty. If only a group is created, leave the user entry empty. - -id user group notes -------------------------------------------------------------------------------- -301 influxdb influxdb -302 mongod mongod -303 gitea gitea -1001 mirror mirror -1002 certbot certbot -1003 collab collab -1004 docker docker docker registry -1005 backup backup -1007 minecraft minecraft diff --git a/users.md b/users.md new file mode 100644 index 0000000..7601659 --- /dev/null +++ b/users.md @@ -0,0 +1,20 @@ +# List of reserved UID and GID numbers + +This file lists all users and groups that have reserved uid/gid and are +created using ansible rules. If a user/group pair is created, they share +the same uid/gid. If a user is member of a system group, leave the group +entry empty. If only a group is created, leave the user entry empty. + +| id | user | group | notes | +|------|------------|------------|-----------------| +| 301 | influxdb | influxdb | | +| 302 | mongod | mongod | | +| 303 | forgejo | forgejo | | +| 305 | prometheus | prometheus | | +| 306 | backup | backup | | +| 307 | minecraft | minecraft | | +| 308 | certbot | certbot | | +| 309 | mirror | mirror | | +| 310 | collab | collab | | +| 311 | docker | docker | docker registry | +| 312 | logsync | logsync | nginx log sync |