Compare commits

..

27 commits

Author SHA1 Message Date
d60d790be5 Don't log cronjob start/stop in /var/log/auth. 2026-03-30 14:55:51 +00:00
44b93b9422 Update logfile configurations. 2026-03-30 14:55:19 +00:00
9f1e0b51c8 Update cronjob that creates the 'today' symlink in /data/logs/* 2026-03-30 14:54:16 +00:00
30d159d86f Update pkglist - add dbus. 2026-03-30 14:39:53 +00:00
f4ce19ddbd Update birth-certificate time from bootstrap.log. 2026-03-30 14:39:36 +00:00
4389d832fd Update various .gitignore files. 2026-03-30 14:39:02 +00:00
1adc4610af Ignore certificate files. 2026-03-21 20:58:06 +00:00
84b86debdc Update git metadata files. 2026-03-21 20:55:57 +00:00
cdc8c86955 Use system dehydrated. 2026-03-21 20:53:09 +00:00
ecf58dbcf6 sshguard configuration. 2026-03-21 20:36:56 +00:00
61ee3062c6 Add sshguard to firewall. 2026-03-21 20:30:25 +00:00
e6c621f55a Add rsyncd configuration. 2026-03-21 20:17:07 +00:00
3bb3fd7928 s-nail configuration. 2026-03-21 18:37:30 +00:00
368b0f2b23 Rename msmtp aliases file. 2026-03-21 18:36:30 +00:00
f9df1c563f Add (empty, for now) fstab. 2026-03-21 18:27:18 +00:00
5e2fcbfb30 Add firewall. 2026-03-21 18:26:46 +00:00
32951fb41a Update default/ settings. 2026-03-21 18:20:59 +00:00
66a5922794 Add Dokuwiki configuration. 2026-03-21 18:19:21 +00:00
1865e047c6 Add birth certificate. 2026-03-21 17:12:03 +00:00
f7cfc6c21e Update pkglist. 2026-03-21 16:59:26 +00:00
7b0b11ae89 Update group/passwd databases. Add startup/shutdown scripts. 2026-03-21 16:59:07 +00:00
71408d28fd Use a temporary nameserver. 2026-03-21 16:40:44 +00:00
8c986d5f5c Add Devuan to supported package list creation. 2026-03-21 16:40:18 +00:00
47d27f3e4b Add motd. 2026-03-21 16:38:37 +00:00
69e3e23208 Set logging for Kerberos in krb5.conf. 2026-03-21 16:34:13 +00:00
cfad7c1944 Add symlinks in /usr/{bin,sbin,lib} directories. 2026-03-21 16:29:30 +00:00
2e2acfa0cd Add THB init script. 2026-03-19 20:42:07 +00:00
102 changed files with 2133 additions and 3210 deletions

View file

@ -9,359 +9,521 @@ LmdpdGhvb2tz 1773074781.635958529 1771512801.560006128 root:root 0755 - -
LmdpdGhvb2tzL3Bvc3QtbWVyZ2U= 1757519106.000000000 1757519106.000000000 root:root 0755 - -
LmdpdGhvb2tz 1773074781.635958529 1771512801.560006128 root:root 0755 - -
LmdpdGhvb2tzL3ByZS1jb21taXQ= 1757519106.000000000 1757519106.000000000 root:root 0755 - -
LmdpdGlnbm9yZQ== 1762025173.020942279 1757593248.000000000 root:root 0644 - -
LmdpdGlnbm9yZQ== 1774107585.673027919 1757593248.000000000 root:root 0644 - -
LmdpdG1vZHVsZXM= 1757607701.000000000 1757607701.000000000 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRjLy5naXRpZ25vcmU= 1773946669.402887347 1757611781.000000000 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZXRjLy5naXRpZ25vcmU= 1774123924.683508430 1757611781.000000000 root:root 0644 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
YXBhY2hlMg== - -
ZXRjL2FwYWNoZTIvLmdpdGlnbm9yZQ== 1766069108.043264156 1757775932.000000000 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
YXBhY2hlMg== - -
ZXRjL2FwYWNoZTIvYXBhY2hlMi5jb25m 1773343425.497690175 1757785514.000000000 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
YXBhY2hlMg== - -
bW9kcy1lbmFibGVk - -
ZXRjL2FwYWNoZTIvbW9kcy1lbmFibGVkL2F1dGhuX2NvcmUubG9hZA== 1771512801.564006063 1771512801.564006063 root:root 0777 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
YXBhY2hlMg== - -
bW9kcy1lbmFibGVk - -
ZXRjL2FwYWNoZTIvbW9kcy1lbmFibGVkL2F1dGhuX2ZpbGUubG9hZA== 1771512801.564006063 1771512801.564006063 root:root 0777 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
YXBhY2hlMg== - -
bW9kcy1lbmFibGVk - -
ZXRjL2FwYWNoZTIvbW9kcy1lbmFibGVkL2F1dGh6X2NvcmUubG9hZA== 1771512801.564006063 1771512801.564006063 root:root 0777 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
YXBhY2hlMg== - -
bW9kcy1lbmFibGVk - -
ZXRjL2FwYWNoZTIvbW9kcy1lbmFibGVkL2F1dGh6X3VzZXIubG9hZA== 1771512801.564006063 1771512801.564006063 root:root 0777 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
YXBhY2hlMg== - -
bW9kcy1lbmFibGVk - -
ZXRjL2FwYWNoZTIvbW9kcy1lbmFibGVkL2NnaWQubG9hZA== 1771512801.564006063 1771512801.564006063 root:root 0777 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
YXBhY2hlMg== - -
bW9kcy1lbmFibGVk - -
ZXRjL2FwYWNoZTIvbW9kcy1lbmFibGVkL2RlZmxhdGUubG9hZA== 1771512801.564006063 1771512801.564006063 root:root 0777 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
YXBhY2hlMg== - -
bW9kcy1lbmFibGVk - -
ZXRjL2FwYWNoZTIvbW9kcy1lbmFibGVkL2ZpbHRlci5sb2Fk 1771512801.568005995 1771512801.568005995 root:root 0777 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
YXBhY2hlMg== - -
bW9kcy1lbmFibGVk - -
ZXRjL2FwYWNoZTIvbW9kcy1lbmFibGVkL2h0dHAyLmxvYWQ= 1771512801.568005995 1771512801.568005995 root:root 0777 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
YXBhY2hlMg== - -
bW9kcy1lbmFibGVk - -
ZXRjL2FwYWNoZTIvbW9kcy1lbmFibGVkL2luY2x1ZGUubG9hZA== 1771512801.568005995 1771512801.568005995 root:root 0777 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
YXBhY2hlMg== - -
bW9kcy1lbmFibGVk - -
ZXRjL2FwYWNoZTIvbW9kcy1lbmFibGVkL3Byb3h5LmxvYWQ= 1771512801.568005995 1771512801.568005995 root:root 0777 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
YXBhY2hlMg== - -
bW9kcy1lbmFibGVk - -
ZXRjL2FwYWNoZTIvbW9kcy1lbmFibGVkL3Byb3h5X2ZjZ2kubG9hZA== 1771512801.568005995 1771512801.568005995 root:root 0777 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
YXBhY2hlMg== - -
bW9kcy1lbmFibGVk - -
ZXRjL2FwYWNoZTIvbW9kcy1lbmFibGVkL3Byb3h5X2h0dHAubG9hZA== 1773512305.071354981 1773512305.071354981 root:root 0777 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
YXBhY2hlMg== - -
bW9kcy1lbmFibGVk - -
ZXRjL2FwYWNoZTIvbW9kcy1lbmFibGVkL3Jld3JpdGUubG9hZA== 1773519967.649760800 1773519967.649760800 root:root 0777 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
YXBhY2hlMg== - -
bW9kcy1lbmFibGVk - -
ZXRjL2FwYWNoZTIvbW9kcy1lbmFibGVkL3NvY2FjaGVfc2htY2IubG9hZA== 1773343134.250327036 1773343134.250327036 root:root 0777 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
YXBhY2hlMg== - -
bW9kcy1lbmFibGVk - -
ZXRjL2FwYWNoZTIvbW9kcy1lbmFibGVkL3NzbC5sb2Fk 1773343014.364235719 1773343014.364235719 root:root 0777 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
YXBhY2hlMg== - -
c2l0ZXMtYXZhaWxhYmxl - -
ZXRjL2FwYWNoZTIvc2l0ZXMtYXZhaWxhYmxlLy5naXRpZ25vcmU= 1766069274.068541443 1766069263.648712326 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
YXBhY2hlMg== - -
c2l0ZXMtYXZhaWxhYmxl - -
ZXRjL2FwYWNoZTIvc2l0ZXMtYXZhaWxhYmxlL2NvcmUuc2xhY2t3YXJlLnVrLm5ldC5jb25m 1773519943.102151242 1757785113.000000000 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
YXBhY2hlMg== - -
c2l0ZXMtZW5hYmxlZA== - -
ZXRjL2FwYWNoZTIvc2l0ZXMtZW5hYmxlZC8wMC1jb3JlLnNsYWNrd2FyZS51ay5uZXQuY29uZg== 1773340506.404142422 1773340506.404142422 root:root 0777 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
YXB0 - -
ZXRjL2FwdC8uZ2l0aWdub3Jl 1762532662.236312315 1762532566.409854495 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
YXB0 - -
cHJlZmVyZW5jZXMuZA== - -
ZXRjL2FwdC9wcmVmZXJlbmNlcy5kL3N1cnk= 1762021809.456432672 1762021809.456432672 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
YXB0 - -
c291cmNlcy5saXN0LmQ= - -
ZXRjL2FwdC9zb3VyY2VzLmxpc3QuZC9mZC5saXN0 1762021706.378133066 1762021706.374133133 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
YXB0 - -
c291cmNlcy5saXN0LmQ= - -
ZXRjL2FwdC9zb3VyY2VzLmxpc3QuZC9zdXJ5Lmxpc3Q= 1762021706.378133066 1762021706.378133066 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZXRjL2JpcnRoLWNlcnRpZmljYXRl 1774714793.333168516 1774112616.134109991 root:root 0644 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
Ym9vdC5k - -
ZXRjL2Jvb3QuZC9wdXNob3Zlci1hbGVydA== 1773658239.854435424 1758225089.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
Y2VydGlmaWNhdGVz - -
ZXRjL2NlcnRpZmljYXRlcy8uZ2l0aWdub3Jl 1774126655.398873237 1774126655.398873237 root:root 0644 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
Y3Jvbi4xNW1pbg== - -
ZXRjL2Nyb24uMTVtaW4vLmdpdGlnbm9yZQ== 1762535468.567176697 1762535289.358058790 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
Y3Jvbi5k - -
ZXRjL2Nyb24uZC8uZ2l0aWdub3Jl 1762535453.203423781 1762535289.358058790 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRjL2Nyb24uZC8uZ2l0aWdub3Jl 1774113745.435355910 1762535289.358058790 root:root 0644 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
Y3Jvbi5kYWlseQ== - -
ZXRjL2Nyb24uZGFpbHkvLmdpdGlnbm9yZQ== 1762538383.748288196 1762535499.146684944 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRjL2Nyb24uZGFpbHkvLmdpdGlnbm9yZQ== 1774882375.073085385 1762535499.146684944 root:root 0644 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
Y3Jvbi5kYWlseQ== - -
ZXRjL2Nyb24uZGFpbHkvMC1yb3RhdGUtbG9ncy1zeW1saW5rcw== 1773074830.431179720 1773074830.431179720 root:root 0777 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRjL2Nyb24uZGFpbHkvMC1yb3RhdGUtbG9ncy10b2RheS1zeW1saW5r 1774882348.257522426 1774882348.257522426 root:root 0777 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
Y3Jvbi5kYWlseQ== - -
ZXRjL2Nyb24uZGFpbHkvMTAtZGVoeWRyYXRlZA== 1773074830.431179720 1773074830.431179720 root:root 0777 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
Y3Jvbi5kYWlseQ== - -
ZXRjL2Nyb24uZGFpbHkvNS11cGRhdGUtcGFja2FnZXMtbGlzdA== 1773074830.431179720 1773074830.431179720 root:root 0777 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
Y3Jvbi5kYWlseQ== - -
ZXRjL2Nyb24uZGFpbHkvNy13YXJuLWdpdC1zdGF0dXM= 1773074830.431179720 1773074830.431179720 root:root 0777 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
Y3Jvbi5ob3VybHk= - -
ZXRjL2Nyb24uaG91cmx5Ly5naXRpZ25vcmU= 1762535518.534373147 1762535518.534373147 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
Y3Jvbi5tb250aGx5 - -
ZXRjL2Nyb24ubW9udGhseS8uZ2l0aWdub3Jl 1762535548.045898541 1762535548.045898541 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
Y3Jvbi53ZWVrbHk= - -
ZXRjL2Nyb24ud2Vla2x5Ly5naXRpZ25vcmU= 1762628453.620630321 1762535530.470181196 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
Y3Jvbi53ZWVrbHk= - -
ZXRjL2Nyb24ud2Vla2x5L2NsZWFuLXBocA== 1773074830.431179720 1773074830.431179720 root:root 0777 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
Y3Jvbi55ZWFybHk= - -
ZXRjL2Nyb24ueWVhcmx5Ly5naXRpZ25vcmU= 1762535568.001577608 1762535568.001577608 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZXRjL2Nyb250YWI= 1762534976.223094581 1757593504.000000000 root:root 0600 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZGVmYXVsdA== - -
ZXRjL2RlZmF1bHQvLmdpdGlnbm9yZQ== 1773952746.050042264 1762624148.166366444 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRjL2RlZmF1bHQvLmdpdGlnbm9yZQ== 1774877901.613747641 1762624148.166366444 root:root 0644 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZGVmYXVsdA== - -
ZXRjL2RlZmF1bHQvZG9rdXdpa2k= 1773952381.644085099 1773517662.000000000 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRjL2RlZmF1bHQvY3Jvbg== 1774114880.928470664 1771511324.000000000 root:root 0644 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZGVmYXVsdA== - -
ZXRjL2RlZmF1bHQvZG9rdXdpa2k= 1774114972.074960982 1773517662.000000000 root:root 0644 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZGVmYXVsdA== - -
ZXRjL2RlZmF1bHQvcHJvbWV0aGV1cw== 1773513253.988425139 1773502158.000000000 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZGVmYXVsdA== - -
ZXRjL2RlZmF1bHQvcHJvbWV0aGV1cy1hbGVydG1hbmFnZXI= 1741526314.000000000 1773502158.000000000 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZGVmYXVsdA== - -
ZXRjL2RlZmF1bHQvcHJvbWV0aGV1cy1ub2RlLWV4cG9ydGVy 1773511187.568917165 1762023153.000000000 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZGVmYXVsdA== - -
ZXRjL2RlZmF1bHQvcm90YXRlLWxvZ3Mtc3ltbGlua3M= 1758555243.000000000 1758552192.000000000 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRjL2RlZmF1bHQvcnN5bmM= 1774115973.482452959 1764289744.000000000 root:root 0644 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZGVmYXVsdA== - -
ZXRjL2RlZmF1bHQvdGVycmFmb3JtLWh0dHAtYmFja2VuZA== 1773511563.759009356 1757595391.000000000 root:root 0600 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRjL2RlZmF1bHQvdGVycmFmb3JtLWh0dHAtYmFja2VuZA== 1774116075.948769497 1757595391.000000000 root:root 0600 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZGVoeWRyYXRlZA== - -
ZXRjL2RlaHlkcmF0ZWQvLmdpdGlnbm9yZQ== 1758038054.000000000 1758038054.000000000 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZGVoeWRyYXRlZA== - -
YWNjb3VudHM= - -
ZXRjL2RlaHlkcmF0ZWQvYWNjb3VudHMvLmdpdGlnbm9yZQ== 1757873230.000000000 1757873230.000000000 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZGVoeWRyYXRlZA== - -
YWNjb3VudHM= - -
ZXRjL2RlaHlkcmF0ZWQvYWNjb3VudHMvYUhSMGNITTZMeTloWTIxbExYWXdNaTVoY0drdWJHVjBjMlZ1WTNKNWNIUXViM0puTDJScGNtVmpkRzl5ZVFvLnRhci5ncGc= 1773159494.828502366 1757873275.000000000 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZGVoeWRyYXRlZA== - -
YXJjaGl2ZQ== - -
ZXRjL2RlaHlkcmF0ZWQvYXJjaGl2ZS8uZ2l0aWdub3Jl 1757874259.000000000 1757873451.000000000 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZGVoeWRyYXRlZA== - -
Y2VydHM= - -
ZXRjL2RlaHlkcmF0ZWQvY2VydHMvLmdpdGlnbm9yZQ== 1757874303.000000000 1757873537.000000000 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZGVoeWRyYXRlZA== - -
Y29uZi5k - -
ZXRjL2RlaHlkcmF0ZWQvY29uZi5kLy5naXRrZWVwZGly 1773342473.728835264 1773342473.728835264 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZGVoeWRyYXRlZA== - -
ZXRjL2RlaHlkcmF0ZWQvY29uZmln 1773422158.392330219 1757862077.000000000 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZGVoeWRyYXRlZA== - -
ZXRjL2RlaHlkcmF0ZWQvZG9tYWlucw== 1757862328.000000000 1757862077.000000000 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZGVoeWRyYXRlZA== - -
ZG9tYWlucy5k - -
ZXRjL2RlaHlkcmF0ZWQvZG9tYWlucy5kL19leGFtcGxlXw== 1773422197.987710884 1757862077.000000000 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZGVoeWRyYXRlZA== - -
aG9va3M= - -
ZXRjL2RlaHlkcmF0ZWQvaG9va3MvZGVmYXVsdA== 1773342632.190315764 1757862077.000000000 root:root 0755 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZG9rdXdpa2k= - -
ZXRjL2Rva3V3aWtpLy5naXRpZ25vcmU= 1774878145.441786034 1774878145.441786034 root:root 0644 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZG9rdXdpa2k= - -
ZXRjL2Rva3V3aWtpLy5odGFjY2Vzcw== 1722839243.000000000 1773517662.000000000 root:root 0644 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZG9rdXdpa2k= - -
ZXRjL2Rva3V3aWtpL2FjbC5hdXRoLnBocA== 1746154701.000000000 1773517662.000000000 root:www-data 0777 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZG9rdXdpa2k= - -
ZXRjL2Rva3V3aWtpL2FjbC5hdXRoLnBocC5kaXN0 1722839243.000000000 1773517662.000000000 root:root 0644 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZG9rdXdpa2k= - -
ZXRjL2Rva3V3aWtpL2Fjcm9ueW1zLmNvbmY= 1722839243.000000000 1773517662.000000000 root:www-data 0664 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZG9rdXdpa2k= - -
ZXRjL2Rva3V3aWtpL2FwYWNoZS5jb25m 1774881241.459529288 1774881241.459529288 root:root 0644 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZG9rdXdpa2k= - -
ZXRjL2Rva3V3aWtpL2Rva3V3aWtpLnBocA== 1746154701.000000000 1773517662.000000000 root:www-data 0664 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZG9rdXdpa2k= - -
ZXRjL2Rva3V3aWtpL2VudGl0aWVzLmNvbmY= 1722839243.000000000 1773517662.000000000 root:www-data 0664 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZG9rdXdpa2k= - -
ZXRjL2Rva3V3aWtpL2ludGVyd2lraS5jb25m 1722839243.000000000 1773517662.000000000 root:www-data 0664 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZG9rdXdpa2k= - -
ZXRjL2Rva3V3aWtpL2xpY2Vuc2UucGhw 1722839243.000000000 1773517662.000000000 root:www-data 0664 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZG9rdXdpa2k= - -
ZXRjL2Rva3V3aWtpL2xvY2FsLnBocA== 1773597191.209498063 1773597191.209498063 root:www-data 0664 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZG9rdXdpa2k= - -
ZXRjL2Rva3V3aWtpL2xvY2FsLnBocC5iYWsucGhw 1773597164.469917468 1773597164.469917468 root:www-data 0664 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZG9rdXdpa2k= - -
ZXRjL2Rva3V3aWtpL2xvY2FsLnBocC5kaXN0 1722839243.000000000 1773517662.000000000 root:root 0644 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZG9rdXdpa2k= - -
ZXRjL2Rva3V3aWtpL21hbmlmZXN0Lmpzb24= 1722839243.000000000 1773517662.000000000 root:www-data 0664 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZG9rdXdpa2k= - -
ZXRjL2Rva3V3aWtpL21lZGlhbWV0YS5waHA= 1722839243.000000000 1773517662.000000000 root:www-data 0664 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZG9rdXdpa2k= - -
ZXRjL2Rva3V3aWtpL21pbWUuY29uZg== 1722839243.000000000 1773517662.000000000 root:www-data 0664 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZG9rdXdpa2k= - -
ZXRjL2Rva3V3aWtpL215c3FsLmNvbmYucGhwLmV4YW1wbGU= 1722839243.000000000 1773517662.000000000 root:root 0644 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZG9rdXdpa2k= - -
ZXRjL2Rva3V3aWtpL3BsdWdpbnMubG9jYWwucGhw 1746154701.000000000 1773517662.000000000 root:www-data 0664 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZG9rdXdpa2k= - -
ZXRjL2Rva3V3aWtpL3BsdWdpbnMucGhw 1722839243.000000000 1773517662.000000000 root:www-data 0664 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZG9rdXdpa2k= - -
ZXRjL2Rva3V3aWtpL3BsdWdpbnMucmVxdWlyZWQucGhw 1722839243.000000000 1773517662.000000000 root:www-data 0664 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZG9rdXdpa2k= - -
ZXRjL2Rva3V3aWtpL3NjaGVtZS5jb25m 1722839243.000000000 1773517662.000000000 root:www-data 0664 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZG9rdXdpa2k= - -
ZXRjL2Rva3V3aWtpL3NtaWxleXMuY29uZg== 1722839243.000000000 1773517662.000000000 root:www-data 0664 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZG9rdXdpa2k= - -
ZXRjL2Rva3V3aWtpL3VzZXJwcmludC5jc3M= 1745221948.000000000 1773517662.000000000 root:www-data 0664 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZG9rdXdpa2k= - -
ZXRjL2Rva3V3aWtpL3VzZXJzLmF1dGgucGhw 1746154701.000000000 1773517662.000000000 root:www-data 0777 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZG9rdXdpa2k= - -
ZXRjL2Rva3V3aWtpL3VzZXJzLmF1dGgucGhwLmRpc3Q= 1722839243.000000000 1773517662.000000000 root:root 0644 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZG9rdXdpa2k= - -
ZXRjL2Rva3V3aWtpL3VzZXJzdHlsZS5jc3M= 1745221948.000000000 1773517662.000000000 root:www-data 0664 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZG9rdXdpa2k= - -
ZXRjL2Rva3V3aWtpL3dvcmRibG9jay5jb25m 1722839243.000000000 1773517662.000000000 root:www-data 0664 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZmlyZXdhbGw= - -
ZXRjL2ZpcmV3YWxsLy5naXRpZ25vcmU= 1773947378.243078506 1773947378.243078506 root:root 0644 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZmlyZXdhbGw= - -
ZXRjL2ZpcmV3YWxsL2RlZmF1bHRfdjQucnVsZXM= 1774124942.942844576 1773861600.980550947 root:root 0644 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZmlyZXdhbGw= - -
ZXRjL2ZpcmV3YWxsL2RlZmF1bHRfdjYucnVsZXM= 1774124987.466117124 1773861600.980550947 root:root 0644 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZXRjL2ZzdGFi 1774103611.886951171 1771501851.000000000 root:root 0644 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZnVzaW9uZGlyZWN0b3J5 - -
ZXRjL2Z1c2lvbmRpcmVjdG9yeS9mdXNpb25kaXJlY3RvcnktYXBhY2hlLmNvbmY= 1740415693.000000000 1762022137.000000000 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZnVzaW9uZGlyZWN0b3J5 - -
ZXRjL2Z1c2lvbmRpcmVjdG9yeS9mdXNpb25kaXJlY3RvcnkuY29uZg== - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZnVzaW9uZGlyZWN0b3J5 - -
ZXRjL2Z1c2lvbmRpcmVjdG9yeS9mdXNpb25kaXJlY3RvcnkuY29uZi5vcmln 1760207207.000000000 1760207207.000000000 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZXRjL2dyb3Vw 1773951237.415059979 1773951237.415059979 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRjL2dzaGFkb3cuZ3Bn 1762628156.813441524 1762447499.282711556 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZXRjL2dzaGFkb3cuZ3Bn 1774112155.713736078 1762447499.282711556 root:root 0644 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZXRjL2hvc3RuYW1l 1757594311.000000000 1757594311.000000000 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZXRjL2hvc3Rz 1762446715.371577485 1757594362.000000000 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
aW5pdC5k - -
ZXRjL2luaXQuZC8uZ2l0aWdub3Jl 1771459200.000000000 1771459200.000000000 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
aW5pdC5k - -
ZXRjL2luaXQuZC90ZXJyYWZvcm0taHR0cC1iYWNrZW5k 1773654405.833829368 1771459200.000000000 root:root 0755 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZXRjL2tyYjUuY29uZg== 1773662876.418407545 1583171707.000000000 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
bGRhcA== - -
ZXRjL2xkYXAvbGRhcC5jb25m 1758374529.000000000 1730112559.000000000 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
bGRhcA== - -
c2NoZW1h - -
ZXRjL2xkYXAvc2NoZW1hLy5naXRpZ25vcmU= 1762628549.507075969 1762628549.507075969 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
bGRhcA== - -
c2NoZW1h - -
ZXRjL2xkYXAvc2NoZW1hL3JmYzIzMDdiaXMuc2NoZW1h 1759835660.000000000 1759835660.000000000 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZXRjL2xvZ2luLmRlZnM= 1771509215.801996599 1745058028.000000000 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRjL21vdGQ= 1762625944.389278724 1756052400.000000000 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRjL21zbXRwLmFsaWFzZXM= 1758035451.000000000 1758035451.000000000 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZXRjL2xvZ3JvdGF0ZS5jb25m 1774126916.834604932 1773949445.000000000 root:root 0644 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
bG9ncm90YXRlLmQ= - -
ZXRjL2xvZ3JvdGF0ZS5kL2FsdGVybmF0aXZlcw== 1774879964.524246639 1736567071.000000000 root:root 0644 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
bG9ncm90YXRlLmQ= - -
ZXRjL2xvZ3JvdGF0ZS5kL2FwYWNoZTI= 1774879843.654206932 1771512073.000000000 root:root 0644 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
bG9ncm90YXRlLmQ= - -
ZXRjL2xvZ3JvdGF0ZS5kL2FwdA== 1774880481.903855753 1753012285.000000000 root:root 0644 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
bG9ncm90YXRlLmQ= - -
ZXRjL2xvZ3JvdGF0ZS5kL2J0bXA= 1774880027.579223999 1773949445.000000000 root:root 0644 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
bG9ncm90YXRlLmQ= - -
ZXRjL2xvZ3JvdGF0ZS5kL2Rwa2c= 1774880076.286434085 1736567071.000000000 root:root 0644 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
bG9ncm90YXRlLmQ= - -
ZXRjL2xvZ3JvdGF0ZS5kL3BocDguNC1mcG0= 1774880108.513911418 1771512192.000000000 root:root 0644 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
bG9ncm90YXRlLmQ= - -
ZXRjL2xvZ3JvdGF0ZS5kL3Byb21ldGhldXM= 1774880202.364389342 1773502158.000000000 root:root 0644 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
bG9ncm90YXRlLmQ= - -
ZXRjL2xvZ3JvdGF0ZS5kL3Byb21ldGhldXMtYWxlcnRtYW5hZ2Vy 1774880211.284244673 1773502158.000000000 root:root 0644 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
bG9ncm90YXRlLmQ= - -
ZXRjL2xvZ3JvdGF0ZS5kL3Byb21ldGhldXMtbm9kZS1leHBvcnRlcg== 1774880189.240602186 1771512342.000000000 root:root 0644 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
bG9ncm90YXRlLmQ= - -
ZXRjL2xvZ3JvdGF0ZS5kL3JzeXNsb2c= 1774880765.223259890 1771512334.000000000 root:root 0644 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
bG9ncm90YXRlLmQ= - -
ZXRjL2xvZ3JvdGF0ZS5kL3d0bXA= 1774880296.026870307 1773949445.000000000 root:root 0644 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
bG9ncm90YXRlLmQ= - -
ZXRjL2xvZ3JvdGF0ZS5kL3d0bXBkYg== 1774880340.794144279 1771511324.000000000 root:root 0644 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZXRjL21vdGQ= 1774109784.320927406 1756052400.000000000 root:root 0644 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZXRjL21zbXRwLWFsaWFzZXM= 1758035451.000000000 1758035451.000000000 root:root 0644 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZXRjL21zbXRwcmMuZ3Bn 1761052674.000000000 1758049424.000000000 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
bmV0d29yaw== - -
ZXRjL25ldHdvcmsvLmdpdGlnbm9yZQ== 1757596572.000000000 1757596572.000000000 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
bmV0d29yaw== - -
ZXRjL25ldHdvcmsvaW50ZXJmYWNlcw== 1762449437.502802342 1762449437.502802342 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
bmV0d29yaw== - -
aW50ZXJmYWNlcy5k - -
ZXRjL25ldHdvcmsvaW50ZXJmYWNlcy5kL2V0aDA= 1762449591.864258045 1762449559.040799058 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
bmV0d29yaw== - -
aW50ZXJmYWNlcy5k - -
ZXRjL25ldHdvcmsvaW50ZXJmYWNlcy5kL2V0aDE= 1762449602.376084790 1762449560.312778093 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
cGFtLmQ= - -
ZXRjL3BhbS5kLy5naXRpZ25vcmU= 1774714455.970711834 1774714433.803076074 root:root 0644 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
cGFtLmQ= - -
ZXRjL3BhbS5kL2NvbW1vbi1zZXNzaW9uLW5vbmludGVyYWN0aXZl 1774714594.472436072 1771520438.036467174 root:root 0644 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZXRjL3Bhc3N3ZA== 1773951229.999182951 1773951229.999182951 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
cGhw - -
ZXRjL3BocC8uZ2l0aWdub3Jl 1773950303.090525695 1773950303.090525695 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
cGhw - -
OC40 - -
ZXRjL3BocC84LjQvLmdpdGlnbm9yZQ== 1773950864.129246341 1773950864.129246341 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
cGhw - -
OC40 - -
YXBhY2hlMg== - -
ZXRjL3BocC84LjQvYXBhY2hlMi8uZ2l0aWdub3Jl 1773950761.570942616 1773950761.570942616 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
cGhw - -
OC40 - -
YXBhY2hlMg== - -
ZXRjL3BocC84LjQvYXBhY2hlMi9waHAuaW5p 1773248884.583344972 1773248884.583344972 root:root 0777 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
cGhw - -
OC40 - -
Y2xp - -
ZXRjL3BocC84LjQvY2xpLy5naXRpZ25vcmU= 1773950780.838623940 1773950780.838623940 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
cGhw - -
OC40 - -
Y2xp - -
ZXRjL3BocC84LjQvY2xpL3BocC5pbmk= 1773248893.095208163 1773248893.095208163 root:root 0777 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
cGhw - -
OC40 - -
ZnBt - -
ZXRjL3BocC84LjQvZnBtLy5naXRpZ25vcmU= 1773950820.753963759 1773950820.753963759 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
cGhw - -
OC40 - -
ZnBt - -
ZXRjL3BocC84LjQvZnBtL3BocC1mcG0uY29uZg== 1773249914.582789624 1771512192.000000000 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
cGhw - -
OC40 - -
ZnBt - -
ZXRjL3BocC84LjQvZnBtL3BocC5pbmk= 1773248900.295092442 1773248900.295092442 root:root 0777 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
cGhw - -
OC40 - -
ZnBt - -
cG9vbC5k - -
ZXRjL3BocC84LjQvZnBtL3Bvb2wuZC93d3cuY29uZg== 1773343753.212472726 1771512192.000000000 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
cGhw - -
OC40 - -
ZXRjL3BocC84LjQvcGhwLmluaQ== 1773248696.138374022 1773229113.232168334 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
cGhwbGRhcGFkbWlu - -
ZXRjL3BocGxkYXBhZG1pbi8uZ2l0aWdub3Jl 1762628720.800299329 1762628701.308615289 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
cGhwbGRhcGFkbWlu - -
ZXRjL3BocGxkYXBhZG1pbi9jb25maWcucGhwLmdwZw== 1761052640.000000000 1758539944.000000000 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRjL3BrZ2xpc3Q= 1773878402.020187156 1762560002.068536774 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZXRjL3BrZ2xpc3Q= 1774828801.775754388 1762560002.068536774 root:root 0644 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
cHVzaG92ZXItY2xpZW50 - -
ZXRjL3B1c2hvdmVyLWNsaWVudC8uZ2l0aWdub3Jl 1762628624.365862525 1762448145.464092595 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
cHVzaG92ZXItY2xpZW50 - -
ZXRjL3B1c2hvdmVyLWNsaWVudC9kZWZhdWx0LmdwZw== 1762448163.991787320 1762448163.979787518 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRjL3Jlc29sdi5jb25m 1773592997.299303370 1757611605.000000000 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRjL3JzeXNsb2cuY29uZg== 1757785113.000000000 1757785113.000000000 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZXRjL3JjLmxvY2Fs 1774103527.876346454 1741726362.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZXRjL3JjLnNodXRkb3du 1774103509.628649515 1741726362.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZXRjL3Jlc29sdi5jb25m 1774104634.886005823 1757611605.000000000 root:root 0644 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZXRjL3JzeW5jZC5iYW5uZXI= 1774122601.421220111 1774122601.421220111 root:root 0644 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZXRjL3JzeW5jZC5jb25m 1774124018.429973565 1774120279.027354925 root:root 0644 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZXRjL3JzeW5jZC5wYXNzd2QuZ3Bn 1774123884.056173593 1774123884.056173593 root:root 0644 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZXRjL3JzeXNsb2cuY29uZg== 1774881279.786907127 1757785113.000000000 root:root 0644 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZXRjL3MtbmFpbC5yYw== 1774110388.682978693 1774110134.767164228 root:root 0644 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
c2FtYmE= - -
ZXRjL3NhbWJhL3NtYi5jb25m 1762447904.392054475 1758208516.000000000 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
c2FtYmE= - -
ZXRjL3NhbWJhL3NtYnVzZXJz 1758121825.000000000 1758121586.000000000 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRjL3NoYWRvdy5ncGc= 1762628180.969049967 1762447484.598952854 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZXRjL3NoYWRvdy5ncGc= 1774112131.486138136 1762447484.598952854 root:root 0644 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
c2h1dGRvd24uZA== - -
ZXRjL3NodXRkb3duLmQvcHVzaG92ZXItYWxlcnQ= 1773658291.017652815 1758225155.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
c3No - -
ZXRjL3NzaC8uZ2l0aWdub3Jl 1762628843.382312260 1757606957.000000000 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
c3No - -
ZXRjL3NzaC9zc2hfY29uZmln 1757606630.000000000 1757606630.000000000 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
c3No - -
ZXRjL3NzaC9zc2hkX2NvbmZpZw== 1758202229.000000000 1757606896.000000000 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
c3NoZ3VhcmQ= - -
ZXRjL3NzaGd1YXJkL3NzaGd1YXJkLmNvbmY= 1758050700.000000000 1758050700.000000000 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRjL3NzaGd1YXJkLy5naXRpZ25vcmU= 1774125137.895659238 1774125137.895659238 root:root 0644 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
c3NoZ3VhcmQ= - -
ZXRjL3NzaGd1YXJkL3NzaGd1YXJkLmNvbmY= 1774125374.863787370 1758050700.000000000 root:root 0644 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
c3NoZ3VhcmQ= - -
ZXRjL3NzaGd1YXJkL3doaXRlbGlzdA== 1758050235.000000000 1758050235.000000000 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
c3Vkb2Vycy5k - -
ZXRjL3N1ZG9lcnMuZC8uZ2l0aWdub3Jl 1762026765.566662574 1762026765.566662574 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
c3Vkb2Vycy5k - -
ZXRjL3N1ZG9lcnMuZC9kZWZhdWx0cw== 1757599359.000000000 1757599359.000000000 root:root 0640 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
c3Vkb2Vycy5k - -
ZXRjL3N1ZG9lcnMuZC9yb290LWFjY2Vzcw== 1757600157.000000000 1757600157.000000000 root:root 0640 - -
aG9tZQ== 1773074781.647958337 1771512801.576005863 root:root 0755 - -
@ -406,7 +568,7 @@ c2Jpbg== 1767688090.000000000 1767688090.000000000 root:root 0777 - -
b3B0L3NiaW4vY3JvbmpvYi1kZWh5ZHJhdGVk 1758033093.000000000 1757531685.000000000 root:root 0755 - -
b3B0 1771515169.961748163 1771501851.000000000 root:root 0755 - -
c2Jpbg== 1767688090.000000000 1767688090.000000000 root:root 0777 - -
b3B0L3NiaW4vY3JvbmpvYi1yb3RhdGUtbG9ncy1zeW1saW5rcw== 1758555302.000000000 1758224324.000000000 root:root 0755 - -
b3B0L3NiaW4vY3JvbmpvYi1yb3RhdGUtbG9ncy10b2RheS1zeW1saW5r 1774882209.447784765 1774882209.447784765 root:root 0755 - -
b3B0 1771515169.961748163 1771501851.000000000 root:root 0755 - -
c2Jpbg== 1767688090.000000000 1767688090.000000000 root:root 0777 - -
b3B0L3NiaW4vY3JvbmpvYi11cGRhdGUtcGFja2FnZXMtbGlzdA== 1773518953.705866964 1757531121.000000000 root:root 0755 - -
@ -415,86 +577,107 @@ c2Jpbg== 1767688090.000000000 1767688090.000000000 root:root 0777 - -
b3B0L3NiaW4vY3JvbmpvYi13YXJuLWdpdC1zdGF0dXM= 1758221607.000000000 1757591137.000000000 root:root 0755 - -
b3B0 1771515169.961748163 1771501851.000000000 root:root 0755 - -
c2Jpbg== 1767688090.000000000 1767688090.000000000 root:root 0777 - -
b3B0L3NiaW4vZGVoeWRyYXRlZA== 1757531557.000000000 1757531557.000000000 root:root 0755 - -
b3B0 1771515169.961748163 1771501851.000000000 root:root 0755 - -
c2Jpbg== 1767688090.000000000 1767688090.000000000 root:root 0777 - -
b3B0L3NiaW4vcHVzaG92ZXItY2xpZW50 1758224526.000000000 1758224526.000000000 root:root 0755 - -
b3B0 1771515169.961748163 1771501851.000000000 root:root 0755 - -
c2Jpbg== 1767688090.000000000 1767688090.000000000 root:root 0777 - -
b3B0L3NiaW4vdGVycmFmb3JtLWh0dHAtYmFja2VuZA== 1757590543.000000000 1757590543.000000000 root:root 0755 - -
cm9vdA== 1773952633.775904057 1771512801.616005200 root:root 0755 - -
cm9vdA== 1774882471.247517956 1771512801.616005200 root:root 0755 - -
cm9vdC8uYmFzaF9sb2dvdXQ= 1757582867.000000000 1757582867.000000000 root:root 0644 - -
cm9vdA== 1773952633.775904057 1771512801.616005200 root:root 0755 - -
cm9vdA== 1774882471.247517956 1771512801.616005200 root:root 0755 - -
cm9vdC8uYmFzaF9wcm9maWxl 1757584711.000000000 1757584711.000000000 root:root 0644 - -
cm9vdA== 1773952633.775904057 1771512801.616005200 root:root 0755 - -
cm9vdA== 1774882471.247517956 1771512801.616005200 root:root 0755 - -
cm9vdC8uYmFzaHJj 1758887027.000000000 1757586493.000000000 root:root 0644 - -
cm9vdA== 1773952633.775904057 1771512801.616005200 root:root 0755 - -
cm9vdA== 1774882471.247517956 1771512801.616005200 root:root 0755 - -
cm9vdC8uZ2l0Y29uZmln 1757582738.000000000 1757582738.000000000 root:root 0644 - -
cm9vdA== 1773952633.775904057 1771512801.616005200 root:root 0755 - -
cm9vdC8uZ2l0aWdub3Jl 1771509562.912369370 1757600312.000000000 root:root 0644 - -
cm9vdA== 1773952633.775904057 1771512801.616005200 root:root 0755 - -
cm9vdA== 1774882471.247517956 1771512801.616005200 root:root 0755 - -
cm9vdC8uZ2l0aWdub3Jl 1774104492.728356672 1757600312.000000000 root:root 0644 - -
cm9vdA== 1774882471.247517956 1771512801.616005200 root:root 0755 - -
LmxvY2Fs - -
c2hhcmU= - -
bmFubw== - -
cm9vdC8ubG9jYWwvc2hhcmUvbmFuby8uZ2l0aWdub3Jl 1757586210.000000000 1757586210.000000000 root:root 0644 - -
cm9vdA== 1773952633.775904057 1771512801.616005200 root:root 0755 - -
cm9vdA== 1774882471.247517956 1771512801.616005200 root:root 0755 - -
cm9vdC8ubmFub3Jj 1757585756.000000000 1757585756.000000000 root:root 0644 - -
cm9vdA== 1773952633.775904057 1771512801.616005200 root:root 0755 - -
cm9vdA== 1774882471.247517956 1771512801.616005200 root:root 0755 - -
LnNzaA== - -
cm9vdC8uc3NoLy5naXRpZ25vcmU= 1757593349.000000000 1757593349.000000000 root:root 0644 - -
cm9vdA== 1773952633.775904057 1771512801.616005200 root:root 0755 - -
cm9vdA== 1774882471.247517956 1771512801.616005200 root:root 0755 - -
LnNzaA== - -
cm9vdC8uc3NoL2F1dGhvcml6ZWRfa2V5cw== 1757587611.000000000 1757587611.000000000 root:root 0644 - -
cm9vdA== 1773952633.775904057 1771512801.616005200 root:root 0755 - -
cm9vdA== 1774882471.247517956 1771512801.616005200 root:root 0755 - -
c3R1ZmYtdG8ta2VlcA== - -
cm9vdC9zdHVmZi10by1rZWVwL2NsZWFuLWZk 1758994151.000000000 1758992264.000000000 root:root 0755 - -
cm9vdA== 1773952633.775904057 1771512801.616005200 root:root 0755 - -
cm9vdA== 1774882471.247517956 1771512801.616005200 root:root 0755 - -
c3R1ZmYtdG8ta2VlcA== - -
cm9vdC9zdHVmZi10by1rZWVwL2R1bW15LWRlZmF1bHQtbXRh 1762020478.278412865 1762020215.034844513 root:root 0644 - -
cm9vdA== 1773952633.775904057 1771512801.616005200 root:root 0755 - -
cm9vdA== 1774882471.247517956 1771512801.616005200 root:root 0755 - -
c3R1ZmYtdG8ta2VlcA== - -
cm9vdC9zdHVmZi10by1rZWVwL2R1bW15LWRlZmF1bHQtbXRhXzAuMC4xX2FsbC5kZWI= 1762020499.466056182 1762020499.458056317 root:root 0644 - -
dXNy 1774107718.754827355 1771501851.000000000 root:root 0755 - -
dXNyLy5naXRpZ25vcmU= 1774107718.734827685 1774107647.716001993 root:root 0644 - -
dXNy 1774107718.754827355 1771501851.000000000 root:root 0755 - -
Ymlu 1767688090.000000000 1767688090.000000000 root:root 0777 - -
dXNyL2Jpbi8uZ2l0aWdub3Jl 1774110451.861936300 1774107755.910212974 root:root 0644 - -
dXNy 1774107718.754827355 1771501851.000000000 root:root 0755 - -
Ymlu 1767688090.000000000 1767688090.000000000 root:root 0777 - -
dXNyL2Jpbi9tYWls 1774110427.390340069 1774110427.390340069 root:root 0777 - -
dXNy 1774107718.754827355 1771501851.000000000 root:root 0755 - -
Ymlu 1767688090.000000000 1767688090.000000000 root:root 0777 - -
dXNyL2Jpbi9tYWlseA== 1774110428.982313794 1774110428.982313794 root:root 0777 - -
dXNy 1774107718.754827355 1771501851.000000000 root:root 0755 - -
Ymlu 1767688090.000000000 1767688090.000000000 root:root 0777 - -
dXNyL2Jpbi9zZW5kbWFpbA== 1774107735.634548245 1774107735.634548245 root:root 0777 - -
dXNy 1774107718.754827355 1771501851.000000000 root:root 0755 - -
bGli 1767688090.000000000 1767688090.000000000 root:root 0777 - -
dXNyL2xpYi8uZ2l0aWdub3Jl 1774110464.033735481 1774107788.901667453 root:root 0644 - -
dXNy 1774107718.754827355 1771501851.000000000 root:root 0755 - -
bGli 1767688090.000000000 1767688090.000000000 root:root 0777 - -
dXNyL2xpYi9zZW5kbWFpbA== 1774107793.309594570 1774107793.309594570 root:root 0777 - -
dXNy 1774107718.754827355 1771501851.000000000 root:root 0755 - -
c2Jpbg== 1767688090.000000000 1767688090.000000000 root:root 0777 - -
dXNyL3NiaW4vLmdpdGlnbm9yZQ== 1774110477.097519949 1774107768.166010319 root:root 0644 - -
dXNy 1774107718.754827355 1771501851.000000000 root:root 0755 - -
c2Jpbg== 1767688090.000000000 1767688090.000000000 root:root 0777 - -
dXNyL3NiaW4vc2VuZG1haWw= 1774107779.181828175 1774107779.181828175 root:root 0777 - -
dmFy 1773949028.799601180 1771512801.620005134 root:root 0755 - -
dmFyLy5naXRpZ25vcmU= 1773949028.747602042 1758288560.000000000 root:root 0644 - -
dmFy 1773949028.799601180 1771512801.620005134 root:root 0755 - -
bGli 1767688090.000000000 1767688090.000000000 root:root 0777 - -
dmFyL2xpYi8uZ2l0aWdub3Jl 1773949953.372309903 1758288764.000000000 root:root 0644 - -
dmFyL2xpYi8uZ2l0aWdub3Jl 1774877941.677096712 1758288764.000000000 root:root 0644 - -
dmFy 1773949028.799601180 1771512801.620005134 root:root 0755 - -
bGli 1767688090.000000000 1767688090.000000000 root:root 0777 - -
cGhw - -
dmFyL2xpYi9waHAvLmdpdGlnbm9yZQ== 1773235424.683445828 1773235424.683445828 root:root 0644 - -
dmFy 1773949028.799601180 1771512801.620005134 root:root 0755 - -
bGli 1767688090.000000000 1767688090.000000000 root:root 0777 - -
cGhw - -
c2Vzc2lvbnM= - -
dmFyL2xpYi9waHAvc2Vzc2lvbnMvLmdpdGlnbm9yZQ== 1773949643.981426897 1773948904.265660845 root:root 0644 - -
bG9n - -
dmFyL2xvZy8uZ2l0aWdub3Jl 1774127028.984774165 1774127028.984774165 root:root 0644 - -
dmFy 1773949028.799601180 1771512801.620005134 root:root 0755 - -
dG1w 1773942460.457147071 1771501870.000000000 root:root 1777 - -
bG9n - -
QXJjaGl2ZWQ= - -
dmFyL2xvZy9BcmNoaXZlZC8uZ2l0aWdub3Jl 1774126984.505500258 1774126984.505500258 root:root 0644 - -
dmFy 1773949028.799601180 1771512801.620005134 root:root 0755 - -
dG1w 1774830023.084001864 1771501870.000000000 root:root 1777 - -
dmFyL3RtcC8uZ2l0aWdub3Jl 1771459200.000000000 1771459200.000000000 root:root 0644 - -
dmFy 1773949028.799601180 1771512801.620005134 root:root 0755 - -
dG1w 1773942460.457147071 1771501870.000000000 root:root 1777 - -
cGhwLXVwbG9hZHM= - -
dmFyL3RtcC9waHAtdXBsb2Fkcy8uZ2l0aWdub3Jl 1773949181.645073322 1773949181.645073322 root:root 0644 - -
dmFy 1773949028.799601180 1771512801.620005134 root:root 0755 - -
d3d3 - -
dmFyL3d3dy8uZ2l0aWdub3Jl 1773949001.724048991 1773949001.724048991 root:root 0644 - -
dmFy 1773949028.799601180 1771512801.620005134 root:root 0755 - -
d3d3 - -
ZGVoeWRyYXRlZA== - -
dmFyL3d3dy9kZWh5ZHJhdGVkLy5naXRpZ25vcmU= 1773946447.886574894 1773340286.179664904 root:root 0644 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZXRjL3NoYWRvdw== 1773951229.983183217 1773951229.983183217 root:shadow 0640 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZXRjL3NoYWRvdy0= 1762449439.000000000 1762449439.000000000 root:shadow 0640 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
ZXRjL3N1ZG9lcnM= 1751262933.000000000 1751262933.000000000 root:root 0440 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
c3Vkb2Vycy5k - -
ZXRjL3N1ZG9lcnMuZC9SRUFETUU= 1751262933.000000000 1751262933.000000000 root:root 0440 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
c3Vkb2Vycy5k - -
ZXRjL3N1ZG9lcnMuZC9kZWZhdWx0cw== 1757599359.000000000 1757599359.000000000 root:root 0640 - -
ZXRj 1773951237.415059979 1771501908.000000000 root:root 0755 - -
ZXRj 1774881279.806906802 1771501908.000000000 root:root 0755 - -
c3Vkb2Vycy5k - -
ZXRjL3N1ZG9lcnMuZC9yb290LWFjY2Vzcw== 1757600157.000000000 1757600157.000000000 root:root 0640 - -
aG9tZQ== 1773074781.647958337 1771512801.576005863 root:root 0755 - -

@ -1 +1 @@
Subproject commit 6f956ff56af0a65b6dd8f84aa845031c22998c61
Subproject commit ff06547286837af17b586b256a3d7ac226f2c382

1
.gitignore vendored
View file

@ -17,4 +17,3 @@
/srv/
/sys/
/tmp/
/usr/

47
etc/.gitignore vendored
View file

@ -6,31 +6,19 @@
/alternatives/
/apparmor.d/
/bash.bashrc
/bash_completion
/bash_completion.d/
/bindresvport.blacklist
/binfmt.d/
/ca-certificates/
/ca-certificates.conf
/credstore/
/credstore.encrypted/
/certificates/
/dbus-1/
/ca-certificates/
/debconf.conf
/debian_version
/deluser.conf
/depmod.d/
/dhcpcd.conf
/devuan_version
/dpkg/
/environment
/ethertypes
/fonts/
/freeipmi/
/fstab
/gai.conf
/ghostscript/
/gprofng.rc
/groff/
/group-
/gshadow
/gshadow-
@ -38,8 +26,11 @@
/gssapi_mech.conf
/host.conf
/hosts.*
/inittab
/inputrc
/ipmi/
/insserv/
/insserv.conf
/insserv.conf.d/
/issue
/issue.net
/kernel/
@ -51,52 +42,37 @@
/logcheck/
/lynx/
/machine-id
/magic
/magic.mime
/mail.rc
/mime.types
/mailcap
/mailcap.order
/manpath.config
/mime.types
/modprobe.d/
/modules
/modules-load.d/
/msmtprc
/mtab
/nanorc
/netconfig
/networks
/nftables.conf
/nsswitch.conf
/nvme/
/opt/
/os-release
/pam.conf
/pam.d/
/paperspecs
/passwd-
/perl/
/polkit-1/
/profile
/profile.d/
/protocols
/python3/
/python3.13/
/rc?.d/
/rmt
/rpc
/rsyncd.passwd
/runit/
/security/
/selinux/
/sensors.d/
/sensors3.conf
/services
/sgml/
/shadow
/shadow-
/shells
/skel/
/snmp/
/ssl/
/subgid
/subuid
@ -106,14 +82,11 @@
/supercat/
/sv/
/sysctl.d/
/systemd/
/terminfo/
/tmpfiles.d/
/ucf.conf
/udev/
/ufw/
/update-motd.d/
/vconsole.conf
/vim/
/wgetrc
/xattr.conf
/xdg
/xml

1
etc/birth-certificate Normal file
View file

@ -0,0 +1 @@
Thu 19 Feb 11:50:09 UTC 2026

4
etc/boot.d/pushover-alert Executable file
View file

@ -0,0 +1,4 @@
#!/bin/bash
# Alert that this host is up.
[[ -x /opt/sbin/pushover-client ]] && /opt/sbin/pushover-client -p -1 -m "Boot up: ${HOSTNAME%%.*}"

View file

@ -1,2 +1 @@
/*
!/.gitignore
/.placeholder

View file

@ -1,6 +1,6 @@
/*
!/.gitignore
!/0-rotate-logs-symlinks
!/0-rotate-logs-today-symlink
!/5-update-packages-list
!/7-warn-git-status
!/10-dehydrated

View file

@ -1 +0,0 @@
/opt/sbin/cronjob-rotate-logs-symlinks

View file

@ -0,0 +1 @@
/opt/sbin/cronjob-rotate-logs-today-symlink

View file

@ -1,10 +1,12 @@
/apache-htcacheclean
/cron
/dbus
/devpts
/halt
/hwclock
/locale
/networking
/nss
/openipmi
/rcS
/ssh
/tmpfs
/useradd
/winbind

27
etc/default/cron Normal file
View file

@ -0,0 +1,27 @@
# Cron configuration options
# Whether to read the system's default environment files (if present)
# If set to "yes", cron will set a proper mail charset from the
# locale information. If set to something other than 'yes', the default
# charset 'C' (canonical name: ANSI_X3.4-1968) will be used.
#
# This has no effect on tasks running under cron; their environment can
# only be changed via PAM or from within the crontab; see crontab(5).
READ_ENV="yes"
# Extra options for cron, see cron(8)
#
# For example, to enable LSB name support in /etc/cron.d/, use
# EXTRA_OPTS='-l'
#
# Or, to log standard messages, plus jobs with exit status != 0:
# EXTRA_OPTS='-L 5'
#
# For quick reference, the currently available log levels are:
# 0 no logging (errors are logged regardless)
# 1 log start of jobs
# 2 log end of jobs
# 4 log jobs with exit status != 0
# 8 log the process identifier of child process (in all logs)
#
EXTRA_OPTS="-L 5"

View file

@ -9,7 +9,7 @@ RUN_CLEANUP="true"
# you can use this variable to change this value according to your
# needs.
# (default is 180)
#CLEANUP_MAXDAYS=180
CLEANUP_MAXDAYS=60
# Set to true to remove revisions older than $CLEANUP_MAXDAYS
# (default is false)

View file

@ -1 +0,0 @@
CREATE_DIRS['core.slackware.uk.net']="fusiondirectory samba"

47
etc/default/rsync Normal file
View file

@ -0,0 +1,47 @@
# defaults file for rsync daemon mode
#
# This file is only used for init.d based systems!
# If this system uses systemd, you can specify options etc. for rsync
# in daemon mode by copying /lib/systemd/system/rsync.service to
# /etc/systemd/system/rsync.service and modifying the copy; add required
# options to the ExecStart line.
# start rsync in daemon mode from init.d script?
# only allowed values are "true", "false", and "inetd"
# Use "inetd" if you want to start the rsyncd from inetd,
# all this does is prevent the init.d script from printing a message
# about not starting rsyncd (you still need to modify inetd's config yourself).
RSYNC_ENABLE=true
# which file should be used as the configuration file for rsync.
# This file is used instead of the default /etc/rsyncd.conf
# Warning: This option has no effect if the daemon is accessed
# using a remote shell. When using a different file for
# rsync you might want to symlink /etc/rsyncd.conf to
# that file.
# RSYNC_CONFIG_FILE=
# what extra options to give rsync --daemon?
# that excludes the --daemon; that's always done in the init.d script
# Possibilities are:
# --address=123.45.67.89 (bind to a specific IP address)
# --port=8730 (bind to specified port; default 873)
RSYNC_OPTS=''
# run rsyncd at a nice level?
# the rsync daemon can impact performance due to much I/O and CPU usage,
# so you may want to run it at a nicer priority than the default priority.
# Allowed values are 0 - 19 inclusive; 10 is a reasonable value.
RSYNC_NICE='10'
# run rsyncd with ionice?
# "ionice" does for IO load what "nice" does for CPU load.
# As rsync is often used for backups which aren't all that time-critical,
# reducing the rsync IO priority will benefit the rest of the system.
# See the manpage for ionice for allowed options.
# -c3 is recommended, this will run rsync IO at "idle" priority. Uncomment
# the next line to activate this.
# RSYNC_IONICE='-c3'
# Don't forget to create an appropriate config file,
# else the daemon will not start.

View file

@ -3,5 +3,5 @@ TF_IP="127.0.0.1"
TF_PORT="9200"
TF_STORAGE_DIR="/var/lib/terraform-http-backend"
TF_AUTH_ENABLED="false"
#TF_USERNAME="sysadmin"
#TF_PASSWORD="sunsa"
#TF_USERNAME=""
#TF_PASSWORD=""

View file

@ -8,7 +8,7 @@
# Where the copies of the current certificates/keys should be placed. Comment for no copying.
CERTSDIR="/etc/certificates"
# The syslog facility and tag to use. Comment for no sysloging.
SYSLOG_FACILITY="local1"
SYSLOG_FACILITY="lpr"
SYSLOG_TAG="dehydrated-hooks"
# Where from/to to send emails. Comment for no emailing.
EMAIL_FROM="\"Server: ${HOSTNAME%%.*}\" <noreply@slackware.uk.net>"

1
etc/dokuwiki/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
/wordblock.local.conf

8
etc/dokuwiki/.htaccess Normal file
View file

@ -0,0 +1,8 @@
## no access to the conf directory
<IfModule mod_authz_core.c>
Require all denied
</IfModule>
<IfModule !mod_authz_core.c>
Order allow,deny
Deny from all
</IfModule>

1
etc/dokuwiki/acl.auth.php Symbolic link
View file

@ -0,0 +1 @@
/var/lib/dokuwiki/acl/acl.auth.php

View file

@ -0,0 +1,21 @@
# acl.auth.php
# <?php exit()?>
# Don't modify the lines above
#
# Access Control Lists
#
# Editing this file by hand shouldn't be necessary. Use the ACL
# Manager interface instead.
#
# If your auth backend allows special char like spaces in groups
# or user names you need to urlencode them (only chars <128, leave
# UTF-8 multibyte chars as is)
#
# none 0
# read 1
# edit 2
# create 4
# upload 8
# delete 16
* @ALL 8

View file

@ -0,0 +1,62 @@
# Acronyms.
ACL Access Control List
AFAICS As far as I can see
AFAIK As far as I know
AFAIR As far as I remember
API Application Programming Interface
ASAP As soon as possible
ASCII American Standard Code for Information Interchange
BTW By the way
CMS Content Management System
CSS Cascading Style Sheets
DNS Domain Name System
EOF End of file
EOL End of line
EOM End of message
EOT End of text
FAQ Frequently Asked Questions
FTP File Transfer Protocol
FOSS Free & Open-Source Software
FLOSS Free/Libre and Open Source Software
FUD Fear, Uncertainty, and Doubt
FYI For your information
GB Gigabyte
GHz Gigahertz
GPL GNU General Public License
GUI Graphical User Interface
HTML HyperText Markup Language
IANAL I am not a lawyer (but)
IE Internet Explorer
IIRC If I remember correctly
IMHO In my humble opinion
IMO In my opinion
IOW In other words
IRC Internet Relay Chat
IRL In real life
KISS Keep it simple stupid
LAN Local Area Network
LGPL GNU Lesser General Public License
LOL Laughing out loud
MathML Mathematical Markup Language
MB Megabyte
MHz Megahertz
MSIE Microsoft Internet Explorer
OMG Oh my God
OS Operating System
OSS Open Source Software
OTOH On the other hand
PITA Pain in the Ass
RFC Request for Comments
ROTFL Rolling on the floor laughing
RTFM Read The Fine Manual
spec specification
TIA Thanks in advance
TL;DR Too long; didn't read
TOC Table of Contents
URI Uniform Resource Identifier
URL Uniform Resource Locator
W3C World Wide Web Consortium
WTF? What the f***
WYSIWYG What You See Is What You Get
YMMV Your mileage may vary

0
etc/dokuwiki/apache.conf Normal file
View file

181
etc/dokuwiki/dokuwiki.php Normal file
View file

@ -0,0 +1,181 @@
<?php
/**
* This is DokuWiki's Main Configuration file
*
* All the default values are kept here, you should not modify it but use
* a local.php file instead to override the settings from here.
*
* This is a piece of PHP code so PHP syntax applies!
*
* For help with the configuration and a more detailed explanation of the various options
* see https://www.dokuwiki.org/config
*/
/* Basic Settings */
$conf['title'] = 'DokuWiki'; //what to show in the title
$conf['start'] = 'start'; //name of start page
$conf['lang'] = 'en'; //your language
$conf['template'] = 'dokuwiki'; //see lib/tpl directory
$conf['tagline'] = ''; //tagline in header (if template supports it)
$conf['sidebar'] = 'sidebar'; //name of sidebar in root namespace (if template supports it)
$conf['license'] = 'cc-by-nc-sa'; //see conf/license.php
$conf['savedir'] = '/var/lib/dokuwiki/data'; //where to store all the files
$conf['basedir'] = ''; //absolute dir from serveroot - blank for autodetection
$conf['baseurl'] = ''; //URL to server including protocol - blank for autodetect
$conf['cookiedir'] = ''; //path to use in cookies - blank for basedir
$conf['dmode'] = 0755; //set directory creation mode
$conf['fmode'] = 0644; //set file creation mode
$conf['allowdebug'] = 0; //allow debug output, enable if needed 0|1
/* Display Settings */
$conf['recent'] = 20; //how many entries to show in recent
$conf['recent_days'] = 7; //How many days of recent changes to keep. (days)
$conf['breadcrumbs'] = 10; //how many recent visited pages to show
$conf['youarehere'] = 0; //show "You are here" navigation? 0|1
$conf['fullpath'] = 0; //show full path of the document or relative to datadir only? 0|1
$conf['typography'] = 1; //smartquote conversion 0=off, 1=doublequotes, 2=all quotes
$conf['dformat'] = '%Y/%m/%d %H:%M'; //dateformat accepted by PHPs strftime() function
$conf['signature'] = ' --- //[[@MAIL@|@NAME@]] @DATE@//'; //signature see wiki page for details
$conf['showuseras'] = 'loginname'; // 'loginname' users login name
// 'username' users full name
// 'email' e-mail address (will be obfuscated as per mailguard)
// 'email_link' e-mail address as a mailto: link (obfuscated)
$conf['toptoclevel'] = 1; //Level starting with and below to include in AutoTOC (max. 5)
$conf['tocminheads'] = 3; //Minimum amount of headlines that determines if a TOC is built
$conf['maxtoclevel'] = 3; //Up to which level include into AutoTOC (max. 5)
$conf['maxseclevel'] = 3; //Up to which level create editable sections (max. 5)
$conf['camelcase'] = 0; //Use CamelCase for linking? (I don't like it) 0|1
$conf['deaccent'] = 1; //deaccented chars in pagenames (1) or romanize (2) or keep (0)?
$conf['useheading'] = 0; //use the first heading in a page as its name
$conf['sneaky_index']= 0; //check for namespace read permission in index view (0|1) (1 might cause unexpected behavior)
$conf['hidepages'] = ''; //Regexp for pages to be skipped from RSS, Search and Recent Changes
/* Authentication Settings */
$conf['useacl'] = 0; //Use Access Control Lists to restrict access?
$conf['autopasswd'] = 1; //autogenerate passwords and email them to user
$conf['authtype'] = 'authplain'; //which authentication backend should be used
$conf['passcrypt'] = 'bcrypt'; //Used crypt method (smd5,md5,sha1,ssha,crypt,mysql,my411,bcrypt)
$conf['defaultgroup']= 'user'; //Default groups new Users are added to
$conf['superuser'] = '!!not set!!'; //The admin can be user or @group or comma separated list user1,@group1,user2
$conf['manager'] = '!!not set!!'; //The manager can be user or @group or comma separated list user1,@group1,user2
$conf['profileconfirm'] = 1; //Require current password to confirm changes to user profile
$conf['rememberme'] = 1; //Enable/disable remember me on login
$conf['disableactions'] = ''; //comma separated list of actions to disable
$conf['auth_security_timeout'] = 900; //time (seconds) auth data is considered valid, set to 0 to recheck on every page view
$conf['securecookie'] = 1; //never send HTTPS cookies via HTTP
$conf['samesitecookie'] = 'Lax'; //SameSite attribute for cookies (Lax|Strict|None|Empty)
$conf['remote'] = 0; //Enable/disable remote interfaces
$conf['remoteuser'] = '!!not set!!'; //user/groups that have access to remote interface (comma separated). leave empty to allow all users
$conf['remotecors'] = ''; //enable Cross-Origin Resource Sharing (CORS) for the remote interfaces. Asterisk (*) to allow all origins. leave empty to deny.
/* Antispam Features */
$conf['usewordblock']= 1; //block spam based on words? 0|1
$conf['relnofollow'] = 1; //use rel="ugc nofollow" for external links?
$conf['indexdelay'] = 60*60*24*5; //allow indexing after this time (seconds) default is 5 days
$conf['mailguard'] = 'hex'; //obfuscate email addresses against spam harvesters?
//valid entries are:
// 'visible' - replace @ with [at], . with [dot] and - with [dash]
// 'hex' - use hex entities to encode the mail address
// 'none' - do not obfuscate addresses
$conf['iexssprotect']= 1; // check for JavaScript and HTML in uploaded files 0|1
/* Editing Settings */
$conf['usedraft'] = 1; //automatically save a draft while editing (0|1)
$conf['locktime'] = 15*60; //maximum age for lockfiles (defaults to 15 minutes)
$conf['cachetime'] = 60*60*24; //maximum age for cachefile in seconds (defaults to a day)
/* Link Settings */
// Set target to use when creating links - leave empty for same window
$conf['target']['wiki'] = '';
$conf['target']['interwiki'] = '';
$conf['target']['extern'] = '';
$conf['target']['media'] = '';
$conf['target']['windows'] = '';
/* Media Settings */
$conf['mediarevisions'] = 1; //enable/disable media revisions
$conf['refcheck'] = 1; //check for references before deleting media files
$conf['gdlib'] = 2; //the GDlib version (0, 1 or 2) 2 tries to autodetect
$conf['im_convert'] = ''; //path to ImageMagicks convert (will be used instead of GD)
$conf['jpg_quality'] = '70'; //quality of compression when scaling jpg images (0-100)
$conf['fetchsize'] = 0; //maximum size (bytes) fetch.php may download from extern, disabled by default
/* Notification Settings */
$conf['subscribers'] = 0; //enable change notice subscription support
$conf['subscribe_time'] = 24*60*60; //Time after which digests / lists are sent (in sec, default 1 day)
//Should be smaller than the time specified in recent_days
$conf['notify'] = ''; //send change info to this email (leave blank for nobody)
$conf['registernotify'] = ''; //send info about newly registered users to this email (leave blank for nobody)
$conf['mailfrom'] = ''; //use this email when sending mails
$conf['mailreturnpath'] = ''; //use this email as returnpath for bounce mails
$conf['mailprefix'] = ''; //use this as prefix of outgoing mails
$conf['htmlmail'] = 1; //send HTML multipart mails
$conf['dontlog'] = 'debug'; //logging facilities that should be disabled
$conf['logretain'] = 3; //how many days of logs to keep
/* Syndication Settings */
$conf['sitemap'] = 0; //Create a Google sitemap? How often? In days.
$conf['rss_type'] = 'rss1'; //type of RSS feed to provide, by default:
// 'rss' - RSS 0.91
// 'rss1' - RSS 1.0
// 'rss2' - RSS 2.0
// 'atom' - Atom 0.3
// 'atom1' - Atom 1.0
$conf['rss_linkto'] = 'diff'; //what page RSS entries link to:
// 'diff' - page showing revision differences
// 'page' - the revised page itself
// 'rev' - page showing all revisions
// 'current' - most recent revision of page
$conf['rss_content'] = 'abstract'; //what to put in the items by default?
// 'abstract' - plain text, first paragraph or so
// 'diff' - plain text unified diff wrapped in <pre> tags
// 'htmldiff' - diff as HTML table
// 'html' - the full page rendered in XHTML
$conf['rss_media'] = 'both'; //what should be listed?
// 'both' - page and media changes
// 'pages' - page changes only
// 'media' - media changes only
$conf['rss_update'] = 5*60; //Update the RSS feed every n seconds (defaults to 5 minutes)
$conf['rss_show_summary'] = 1; //Add revision summary to title? 0|1
$conf['rss_show_deleted'] = 1; //Show deleted items 0|1
/* Advanced Settings */
$conf['updatecheck'] = 0; //automatically check for new releases?
$conf['userewrite'] = 0; //this makes nice URLs: 0: off 1: .htaccess 2: internal
$conf['useslash'] = 0; //use slash instead of colon? only when rewrite is on
$conf['sepchar'] = '_'; //word separator character in page names; may be a
// letter, a digit, '_', '-', or '.'.
$conf['canonical'] = 0; //Should all URLs use full canonical http://... style?
$conf['fnencode'] = 'url'; //encode filenames (url|safe|utf-8)
$conf['autoplural'] = 0; //try (non)plural form of nonexistent files?
$conf['compression'] = 'gz'; //compress old revisions: (0: off) ('gz': gnuzip) ('bz2': bzip)
// bz2 generates smaller files, but needs more cpu-power
$conf['gzip_output'] = 0; //use gzip content encoding for the output xhtml (if allowed by browser)
$conf['compress'] = 1; //Strip whitespaces and comments from Styles and JavaScript? 1|0
$conf['cssdatauri'] = 512; //Maximum byte size of small images to embed into CSS, won't work on IE<8
$conf['send404'] = 0; //Send an HTTP 404 status for nonexistent pages?
$conf['broken_iua'] = 0; //Platform with broken ignore_user_abort (IIS+CGI) 0|1
$conf['xsendfile'] = 0; //Use X-Sendfile (1 = lighttpd, 2 = standard)
$conf['renderer_xhtml'] = 'xhtml'; //renderer to use for main page generation
$conf['readdircache'] = 0; //time cache in second for the readdir operation, 0 to deactivate.
$conf['search_nslimit'] = 0; //limit the search to the current X namespaces
$conf['search_fragment'] = 'exact'; //specify the default fragment search behavior
$conf['trustedproxy'] = '^(::1|[fF][eE]80:|127\.|10\.|192\.168\.|172\.((1[6-9])|(2[0-9])|(3[0-1]))\.)';
//Regexp of trusted proxy address when reading IP using HTTP header
// if blank, do not trust any proxy (including local IP)
/* Feature Flags */
$conf['defer_js'] = 1; // Defer javascript to be executed after the page's HTML has been parsed. Setting will be removed in the next release.
$conf['hidewarnings'] = 0; // Hide warnings
/* Network Settings */
$conf['dnslookups'] = 1; //disable to disallow IP to hostname lookups
$conf['jquerycdn'] = 0; //use a CDN for delivering jQuery?
// Proxy setup - if your Server needs a proxy to access the web set these
$conf['proxy']['host'] = '';
$conf['proxy']['port'] = '';
$conf['proxy']['user'] = '';
$conf['proxy']['pass'] = '';
$conf['proxy']['ssl'] = 0;
$conf['proxy']['except'] = '';

View file

@ -0,0 +1,22 @@
# Typography replacements
#
# Order does matter!
#
# You can use HTML entities here, but it is not recommended because it may break
# non-HTML renderers. Use UTF-8 chars directly instead.
<-> ↔
-> →
<- ←
<=> ⇔
=> ⇒
<= ⇐
>> »
<< «
--- —
--
(c) ©
(tm) ™
(r) ®
... …

View file

@ -0,0 +1,43 @@
# Each URL may contain one of these placeholders
# {URL} is replaced by the URL encoded representation of the wikiname
# this is the right thing to do in most cases
# {NAME} this is replaced by the wikiname as given in the document
# only mandatory encoded is done, urlencoding if the link
# is an external URL, or encoding as a wikiname if it is an
# internal link (begins with a colon)
# {SCHEME}
# {HOST}
# {PORT}
# {PATH}
# {QUERY} these placeholders will be replaced with the appropriate part
# of the link when parsed as a URL
# If no placeholder is defined the urlencoded name is appended to the URL
# To prevent losing your added InterWiki shortcuts after an upgrade,
# you should add new ones to interwiki.local.conf
wp https://en.wikipedia.org/wiki/{NAME}
wpfr https://fr.wikipedia.org/wiki/{NAME}
wpde https://de.wikipedia.org/wiki/{NAME}
wpes https://es.wikipedia.org/wiki/{NAME}
wppl https://pl.wikipedia.org/wiki/{NAME}
wpjp https://ja.wikipedia.org/wiki/{NAME}
wpru https://ru.wikipedia.org/wiki/{NAME}
wpmeta https://meta.wikipedia.org/wiki/{NAME}
doku https://www.dokuwiki.org/
rfc https://tools.ietf.org/html/rfc
man http://man.cx/
amazon https://www.amazon.com/dp/{URL}?tag=splitbrain-20
amazon.de https://www.amazon.de/dp/{URL}?tag=splitbrain-21
amazon.uk https://www.amazon.co.uk/dp/{URL}
paypal https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&amp;business=
phpfn https://secure.php.net/{NAME}
skype skype:{NAME}
google https://www.google.com/search?q=
google.de https://www.google.de/search?q=
go https://www.google.com/search?q={URL}&amp;btnI=lucky
user :user:{NAME}
# To support VoIP/SIP/TEL links
callto callto://{NAME}
tel tel:{NAME}

38
etc/dokuwiki/license.php Normal file
View file

@ -0,0 +1,38 @@
<?php
/**
* This file defines multiple available licenses you can license your
* wiki contents under. Do not change this file, but create a
* license.local.php instead.
*/
if(empty($LC)) $LC = empty($conf['lang']) ? 'en' : $conf['lang'];
$license['cc-zero'] = array(
'name' => 'CC0 1.0 Universal',
'url' => 'https://creativecommons.org/publicdomain/zero/1.0/deed.'.$LC,
);
$license['publicdomain'] = array(
'name' => 'Public Domain',
'url' => 'https://creativecommons.org/licenses/publicdomain/deed.'.$LC,
);
$license['cc-by'] = array(
'name' => 'CC Attribution 4.0 International',
'url' => 'https://creativecommons.org/licenses/by/4.0/deed.'.$LC,
);
$license['cc-by-sa'] = array(
'name' => 'CC Attribution-Share Alike 4.0 International',
'url' => 'https://creativecommons.org/licenses/by-sa/4.0/deed.'.$LC,
);
$license['gnufdl'] = array(
'name' => 'GNU Free Documentation License 1.3',
'url' => 'https://www.gnu.org/licenses/fdl-1.3.html',
);
$license['cc-by-nc'] = array(
'name' => 'CC Attribution-Noncommercial 4.0 International',
'url' => 'https://creativecommons.org/licenses/by-nc/4.0/deed.'.$LC,
);
$license['cc-by-nc-sa'] = array(
'name' => 'CC Attribution-Noncommercial-Share Alike 4.0 International',
'url' => 'https://creativecommons.org/licenses/by-nc-sa/4.0/deed.'.$LC,
);

14
etc/dokuwiki/local.php Normal file
View file

@ -0,0 +1,14 @@
<?php
/*
* Dokuwiki's Main Configuration File - Local Settings
* Auto-generated by config plugin
* Run for user: admin
* Date: Sun, 15 Mar 2026 17:53:11 +0000
*/
$conf['template'] = 'mantinedoku';
$conf['license'] = '';
$conf['useacl'] = 1;
$conf['superuser'] = '@admin';
$conf['plugin']['authldap']['attributes'] = array();
$conf['plugin']['toctweak']['tocPosition'] = '1';

View file

@ -0,0 +1,14 @@
<?php
/*
* Dokuwiki's Main Configuration File - Local Settings
* Auto-generated by config plugin
* Run for user: admin
* Date: Sun, 15 Mar 2026 17:52:44 +0000
*/
$conf['template'] = 'mantinedoku';
$conf['license'] = '';
$conf['useacl'] = 1;
$conf['superuser'] = '@admin';
$conf['plugin']['authldap']['attributes'] = array();
$conf['plugin']['toctweak']['tocPosition'] = '9';

View file

@ -0,0 +1,16 @@
<?php
/**
* This is an example of how a local.php could look like.
* Simply copy the options you want to change from dokuwiki.php
* to this file and change them.
*
* When using the installer, a correct local.php file be generated for
* you automatically.
*/
//$conf['title'] = 'My Wiki'; //what to show in the title
//$conf['useacl'] = 1; //Use Access Control Lists to restrict access?
//$conf['superuser'] = 'joe';

View file

@ -0,0 +1,3 @@
{
"display": "standalone"
}

View file

@ -0,0 +1,91 @@
<?php
/**
* This configures which metadata will be editable through
* the media manager. Each field of the array is an array with the
* following contents:
* fieldname - Where data will be saved (EXIF or IPTC field)
* label - key to lookup in the $lang var, if not found printed as is
* htmltype - 'text', 'textarea' or 'date'
* lookups - array additional fields to look up the data (EXIF or IPTC fields)
*
* The fields are not ordered continuously to make inserting additional items
* in between simpler.
*
* This is a PHP snippet, so PHP syntax applies.
*
* Note: $fields is not a global variable and will not be available to any
* other functions or templates later
*
* You may extend or overwrite this variable in an optional
* conf/mediameta.local.php file
*
* For a list of available EXIF/IPTC fields refer to
* http://www.dokuwiki.org/devel:templates:detail.php
*/
$fields = array(
10 => array('Iptc.Headline',
'img_title',
'text'),
20 => array('',
'img_date',
'date',
array('Date.EarliestTime')),
30 => array('',
'img_fname',
'text',
array('File.Name')),
40 => array('Iptc.Caption',
'img_caption',
'textarea',
array('Exif.UserComment',
'Exif.TIFFImageDescription',
'Exif.TIFFUserComment')),
50 => array('Iptc.Byline',
'img_artist',
'text',
array('Exif.TIFFArtist',
'Exif.Artist',
'Iptc.Credit')),
60 => array('Iptc.CopyrightNotice',
'img_copyr',
'text',
array('Exif.TIFFCopyright',
'Exif.Copyright')),
70 => array('',
'img_format',
'text',
array('File.Format')),
80 => array('',
'img_fsize',
'text',
array('File.NiceSize')),
90 => array('',
'img_width',
'text',
array('File.Width')),
100 => array('',
'img_height',
'text',
array('File.Height')),
110 => array('',
'img_camera',
'text',
array('Simple.Camera')),
120 => array('Iptc.Keywords',
'img_keywords',
'text',
array('Exif.Category')),
);

75
etc/dokuwiki/mime.conf Normal file
View file

@ -0,0 +1,75 @@
# Allowed uploadable file extensions and mimetypes are defined here.
# To extend this file it is recommended to create a mime.local.conf
# file. Mimetypes that should be downloadable and not be opened in the
# should be prefixed with a !
jpg image/jpeg
jpeg image/jpeg
gif image/gif
png image/png
webp image/webp
ico image/vnd.microsoft.icon
mp3 audio/mpeg
ogg audio/ogg
wav audio/wav
webm video/webm
ogv video/ogg
mp4 video/mp4
vtt text/vtt
tgz !application/octet-stream
tar !application/x-gtar
gz !application/octet-stream
bz2 !application/octet-stream
zip !application/zip
rar !application/rar
7z !application/x-7z-compressed
pdf application/pdf
ps !application/postscript
rpm !application/octet-stream
deb !application/octet-stream
doc !application/msword
xls !application/msexcel
ppt !application/mspowerpoint
rtf !application/msword
docx !application/vnd.openxmlformats-officedocument.wordprocessingml.document
xlsx !application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
pptx !application/vnd.openxmlformats-officedocument.presentationml.presentation
sxw !application/soffice
sxc !application/soffice
sxi !application/soffice
sxd !application/soffice
odc !application/vnd.oasis.opendocument.chart
odf !application/vnd.oasis.opendocument.formula
odg !application/vnd.oasis.opendocument.graphics
odi !application/vnd.oasis.opendocument.image
odp !application/vnd.oasis.opendocument.presentation
ods !application/vnd.oasis.opendocument.spreadsheet
odt !application/vnd.oasis.opendocument.text
svg image/svg+xml
# You should enable HTML and Text uploads only for restricted Wikis.
# Spammers are known to upload spam pages through unprotected Wikis.
# Note: Enabling HTML opens Cross Site Scripting vulnerabilities
# through JavaScript. Only enable this with trusted users. You
# need to disable the iexssprotect option additionally to
# adding the mime type here
#html text/html
#htm text/html
#txt text/plain
#conf text/plain
#xml text/xml
#csv text/csv
# Also flash may be able to execute arbitrary scripts in the website's
# context
#swf application/x-shockwave-flash

View file

@ -0,0 +1,253 @@
<?php
/*
* This is an example configuration for the mysql auth plugin.
*
* This SQL statements are optimized for following table structure.
* If you use a different one you have to change them accordingly.
* See comments of every statement for details.
*
* TABLE users
* uid login pass firstname lastname email
*
* TABLE groups
* gid name
*
* TABLE usergroup
* uid gid
*
* To use this configuration you have to copy them to local.protected.php
* or at least include this file in local.protected.php.
*/
/* Options to configure database access. You need to set up this
* options carefully, otherwise you won't be able to access you
* database.
*/
$conf['plugin']['authmysql']['server'] = '';
$conf['plugin']['authmysql']['user'] = '';
$conf['plugin']['authmysql']['password'] = '';
$conf['plugin']['authmysql']['database'] = '';
/* This option enables debug messages in the mysql plugin. It is
* mostly useful for system admins.
*/
$conf['plugin']['authmysql']['debug'] = 0;
/* Normally password encryption is done by DokuWiki (recommended) but for
* some reasons it might be useful to let the database do the encryption.
* Set 'forwardClearPass' to '1' and the cleartext password is forwarded to
* the database, otherwise the encrypted one.
*/
$conf['plugin']['authmysql']['forwardClearPass'] = 0;
/* Multiple table operations will be protected by locks. This array tells
* the plugin which tables to lock. If you use any aliases for table names
* these array must also contain these aliases. Any unnamed alias will cause
* a warning during operation. See the example below.
*/
$conf['plugin']['authmysql']['TablesToLock']= array("users", "users AS u","groups", "groups AS g", "usergroup", "usergroup AS ug");
/***********************************************************************/
/* Basic SQL statements for user authentication (required) */
/***********************************************************************/
/* This statement is used to grant or deny access to the wiki. The result
* should be a table with exact one line containing at least the password
* of the user. If the result table is empty or contains more than one
* row, access will be denied.
*
* The plugin accesses the password as 'pass' so an alias might be necessary.
*
* Following patters will be replaced:
* %{user} user name
* %{pass} encrypted or clear text password (depends on 'encryptPass')
* %{dgroup} default group name
*/
$conf['plugin']['authmysql']['checkPass'] = "SELECT pass
FROM usergroup AS ug
JOIN users AS u ON u.uid=ug.uid
JOIN groups AS g ON g.gid=ug.gid
WHERE login='%{user}'
AND name='%{dgroup}'";
/* This statement should return a table with exact one row containing
* information about one user. The field needed are:
* 'pass' containing the encrypted or clear text password
* 'name' the user's full name
* 'mail' the user's email address
*
* Keep in mind that Dokuwiki will access this information through the
* names listed above so aliases might be necessary.
*
* Following patters will be replaced:
* %{user} user name
*/
$conf['plugin']['authmysql']['getUserInfo'] = "SELECT pass, CONCAT(firstname,' ',lastname) AS name, email AS mail
FROM users
WHERE login='%{user}'";
/* This statement is used to get all groups a user is member of. The
* result should be a table containing all groups the given user is
* member of. The plugin accesses the group name as 'group' so an alias
* might be necessary.
*
* Following patters will be replaced:
* %{user} user name
*/
$conf['plugin']['authmysql']['getGroups'] = "SELECT name as `group`
FROM groups g, users u, usergroup ug
WHERE u.uid = ug.uid
AND g.gid = ug.gid
AND u.login='%{user}'";
/***********************************************************************/
/* Additional minimum SQL statements to use the user manager */
/***********************************************************************/
/* This statement should return a table containing all user login names
* that meet certain filter criteria. The filter expressions will be added
* case dependent by the plugin. At the end a sort expression will be added.
* Important is that this list contains no double entries for a user. Each
* user name is only allowed once in the table.
*
* The login name will be accessed as 'user' to an alias might be necessary.
* No patterns will be replaced in this statement but following patters
* will be replaced in the filter expressions:
* %{user} in FilterLogin user's login name
* %{name} in FilterName user's full name
* %{email} in FilterEmail user's email address
* %{group} in FilterGroup group name
*/
$conf['plugin']['authmysql']['getUsers'] = "SELECT DISTINCT login AS user
FROM users AS u
LEFT JOIN usergroup AS ug ON u.uid=ug.uid
LEFT JOIN groups AS g ON ug.gid=g.gid";
$conf['plugin']['authmysql']['FilterLogin'] = "login LIKE '%{user}'";
$conf['plugin']['authmysql']['FilterName'] = "CONCAT(firstname,' ',lastname) LIKE '%{name}'";
$conf['plugin']['authmysql']['FilterEmail'] = "email LIKE '%{email}'";
$conf['plugin']['authmysql']['FilterGroup'] = "name LIKE '%{group}'";
$conf['plugin']['authmysql']['SortOrder'] = "ORDER BY login";
/***********************************************************************/
/* Additional SQL statements to add new users with the user manager */
/***********************************************************************/
/* This statement should add a user to the database. Minimum information
* to store are: login name, password, email address and full name.
*
* Following patterns will be replaced:
* %{user} user's login name
* %{pass} password (encrypted or clear text, depends on 'encryptPass')
* %{email} email address
* %{name} user's full name
*/
$conf['plugin']['authmysql']['addUser'] = "INSERT INTO users
(login, pass, email, firstname, lastname)
VALUES ('%{user}', '%{pass}', '%{email}',
SUBSTRING_INDEX('%{name}',' ', 1),
SUBSTRING_INDEX('%{name}',' ', -1))";
/* This statement should add a group to the database.
* Following patterns will be replaced:
* %{group} group name
*/
$conf['plugin']['authmysql']['addGroup'] = "INSERT INTO groups (name)
VALUES ('%{group}')";
/* This statement should connect a user to a group (a user become member
* of that group).
* Following patterns will be replaced:
* %{user} user's login name
* %{uid} id of a user dataset
* %{group} group name
* %{gid} id of a group dataset
*/
$conf['plugin']['authmysql']['addUserGroup']= "INSERT INTO usergroup (uid, gid)
VALUES ('%{uid}', '%{gid}')";
/* This statement should remove a group fom the database.
* Following patterns will be replaced:
* %{group} group name
* %{gid} id of a group dataset
*/
$conf['plugin']['authmysql']['delGroup'] = "DELETE FROM groups
WHERE gid='%{gid}'";
/* This statement should return the database index of a given user name.
* The plugin will access the index with the name 'id' so an alias might be
* necessary.
* following patters will be replaced:
* %{user} user name
*/
$conf['plugin']['authmysql']['getUserID'] = "SELECT uid AS id
FROM users
WHERE login='%{user}'";
/***********************************************************************/
/* Additional SQL statements to delete users with the user manager */
/***********************************************************************/
/* This statement should remove a user fom the database.
* Following patterns will be replaced:
* %{user} user's login name
* %{uid} id of a user dataset
*/
$conf['plugin']['authmysql']['delUser'] = "DELETE FROM users
WHERE uid='%{uid}'";
/* This statement should remove all connections from a user to any group
* (a user quits membership of all groups).
* Following patterns will be replaced:
* %{uid} id of a user dataset
*/
$conf['plugin']['authmysql']['delUserRefs'] = "DELETE FROM usergroup
WHERE uid='%{uid}'";
/***********************************************************************/
/* Additional SQL statements to modify users with the user manager */
/***********************************************************************/
/* This statements should modify a user entry in the database. The
* statements UpdateLogin, UpdatePass, UpdateEmail and UpdateName will be
* added to updateUser on demand. Only changed parameters will be used.
*
* Following patterns will be replaced:
* %{user} user's login name
* %{pass} password (encrypted or clear text, depends on 'encryptPass')
* %{email} email address
* %{name} user's full name
* %{uid} user id that should be updated
*/
$conf['plugin']['authmysql']['updateUser'] = "UPDATE users SET";
$conf['plugin']['authmysql']['UpdateLogin'] = "login='%{user}'";
$conf['plugin']['authmysql']['UpdatePass'] = "pass='%{pass}'";
$conf['plugin']['authmysql']['UpdateEmail'] = "email='%{email}'";
$conf['plugin']['authmysql']['UpdateName'] = "firstname=SUBSTRING_INDEX('%{name}',' ', 1),
lastname=SUBSTRING_INDEX('%{name}',' ', -1)";
$conf['plugin']['authmysql']['UpdateTarget']= "WHERE uid=%{uid}";
/* This statement should remove a single connection from a user to a
* group (a user quits membership of that group).
*
* Following patterns will be replaced:
* %{user} user's login name
* %{uid} id of a user dataset
* %{group} group name
* %{gid} id of a group dataset
*/
$conf['plugin']['authmysql']['delUserGroup']= "DELETE FROM usergroup
WHERE uid='%{uid}'
AND gid='%{gid}'";
/* This statement should return the database index of a given group name.
* The plugin will access the index with the name 'id' so an alias might
* be necessary.
*
* Following patters will be replaced:
* %{group} group name
*/
$conf['plugin']['authmysql']['getGroupID'] = "SELECT gid AS id
FROM groups
WHERE name='%{group}'";

View file

6
etc/dokuwiki/plugins.php Normal file
View file

@ -0,0 +1,6 @@
<?php
/**
* This file configures the default states of available plugins. All settings in
* the plugins.*.php files will override those here.
*/
$plugins['testing'] = 0;

View file

@ -0,0 +1,12 @@
<?php
/**
* This file configures the enabled/disabled status of plugins, which are also protected
* from changes by the extension manager. These settings will override any local settings.
* It is not recommended to change this file, as it is overwritten on DokuWiki upgrades.
*/
$plugins['acl'] = 1;
$plugins['authplain'] = 1;
$plugins['extension'] = 1;
$plugins['config'] = 1;
$plugins['usermanager'] = 1;
$plugins['template:dokuwiki'] = 1; // not a plugin, but this should not be uninstalled either

11
etc/dokuwiki/scheme.conf Normal file
View file

@ -0,0 +1,11 @@
#Add URL schemes you want to be recognized as links here
http
https
telnet
gopher
wais
ftp
ed2k
irc
ldap

28
etc/dokuwiki/smileys.conf Normal file
View file

@ -0,0 +1,28 @@
# Smileys configured here will be replaced by the
# configured images in the smiley directory
8-) cool.svg
8-O eek.svg
8-o eek.svg
:-( sad.svg
:-) smile.svg
=) smile2.svg
:-/ doubt.svg
:-\ doubt2.svg
:-? confused.svg
:-D biggrin.svg
:-P razz.svg
:-o surprised.svg
:-O surprised.svg
:-x silenced.svg
:-X silenced.svg
:-| neutral.svg
;-) wink.svg
m( facepalm.svg
^_^ fun.svg
:?: question.svg
:!: exclaim.svg
LOL lol.svg
FIXME fixme.svg
DELETEME deleteme.svg

View file

@ -0,0 +1 @@
/* Place customisations to print mode style sheet here */

1
etc/dokuwiki/users.auth.php Symbolic link
View file

@ -0,0 +1 @@
/var/lib/dokuwiki/acl/users.auth.php

View file

@ -0,0 +1,10 @@
# users.auth.php
# <?php exit()?>
# Don't modify the lines above
#
# Userfile
#
# Format:
#
# login:passwordhash:Real Name:email:groups,comma,separated

View file

@ -0,0 +1 @@
/* Place customisations to screen mode style sheet here */

View file

@ -0,0 +1,29 @@
# This blacklist is maintained by the DokuWiki community
# patches welcome
#
https?:\/\/(\S*?)(-side-effects|top|pharm|pill|discount|discount-|deal|price|order|now|best|cheap|cheap-|online|buy|buy-|sale|sell)(\S*?)(cialis|viagra|prazolam|xanax|zanax|soma|vicodin|zenical|xenical|meridia|paxil|prozac|claritin|allegra|lexapro|wellbutrin|zoloft|retin|valium|levitra|phentermine)
https?:\/\/(\S*?)(bi\s*sex|gay\s*sex|fetish|incest|penis|\brape\b)
zoosex
gang\s*bang
facials
ladyboy
\btits\b
bolea\.com
52crystal
baida\.org
web-directory\.awardspace\.us
korsan-team\.com
BUDA TAMAMDIR
wow-powerleveling-wow\.com
wow gold
wow-gold\.dinmo\.cn
downgrade-vista\.com
downgradetowindowsxp\.com
elegantugg\.com
classicedhardy\.com
research-service\.com
https?:\/\/(\S*?)(2-pay-secure|911essay|academia-research|anypapers|applicationessay|bestbuyessay|bestdissertation|bestessay|bestresume|besttermpaper|businessessay|college-paper|customessay|custom-made-paper|custom-writing|degree-?result|dissertationblog|dissertation-service|dissertations?expert|essaybank|essay-?blog|essaycapital|essaylogic|essaymill|essayontime|essaypaper|essays?land|essaytownsucks|essay-?writ|fastessays|freelancercareers|genuinecontent|genuineessay|genuinepaper|goessay|grandresume|killer-content|ma-dissertation|managementessay|masterpaper|mightystudent|needessay|researchedge|researchpaper-blog|resumecvservice|resumesexperts|resumesplanet|rushessay|samedayessay|superiorcontent|superiorpaper|superiorthesis|term-paper|termpaper-blog|term-paper-research|thesisblog|universalresearch|valwriting|vdwriters|wisetranslation|writersassembly|writers\.com\.ph|writers\.ph)
flatsinmumbai\.co\.in
https?:\/\/(\S*?)penny-?stock
mattressreview\.biz
(just|simply) (my|a) profile (site|webpage|page)

2
etc/firewall/.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
/state_v4.rules
/state_v6.rules

View file

@ -0,0 +1,24 @@
# These rules are applied as the default firewall when there are no state rules to be applied.
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
:sshguard - [0:0]
-A INPUT -m conntrack --ctstate INVALID -j DROP
-A INPUT -i lo -j ACCEPT
-A INPUT -s 10.254.0.0/24 -i eth1 -j ACCEPT
-A INPUT -s 5.101.171.208/28 -i eth0 -j ACCEPT
-A INPUT -s 172.236.16.105/32 -i eth0 -j ACCEPT
-A INPUT -s 185.176.90.169/32 -i eth0 -j ACCEPT
-A INPUT -s 145.40.182.204/32 -i eth0 -j ACCEPT
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT
-A INPUT -p icmp -m icmp --icmp-type 0 -j ACCEPT
-A INPUT -p icmp -m icmp --icmp-type 3 -j ACCEPT
-A INPUT -p icmp -m icmp --icmp-type 11 -j ACCEPT
-A INPUT -p icmp -m icmp --icmp-type 12 -j ACCEPT
-A INPUT -j sshguard
-A INPUT -p tcp -m multiport --dports 22,25422 -m conntrack --ctstate NEW -j ACCEPT
-A INPUT -p tcp -m tcp --dport 873 -m conntrack --ctstate NEW -j ACCEPT
-A INPUT -p tcp -m tcp --dport 25443 -m conntrack --ctstate NEW -j ACCEPT
COMMIT

View file

@ -0,0 +1,26 @@
# These rules are applied as the default firewall when there are no state rules to be applied.
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
:sshguard - [0:0]
-A INPUT -m conntrack --ctstate INVALID -j DROP
-A INPUT -i lo -j ACCEPT
-A INPUT -s 2a01:a500:2981:1::/64 -i eth0 -j ACCEPT
-A INPUT -s 2600:3c13::2000:50ff:fef4:7f56/128 -i eth0 -j ACCEPT
-A INPUT -s 2a07:4580:b0d:57f::169/128 -i eth0 -j ACCEPT
-A INPUT -s 2001:470:1f1d:58::/64 -i eth0 -j ACCEPT
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p ipv6-icmp -m icmp6 --icmpv6-type 128 -j ACCEPT
-A INPUT -p ipv6-icmp -m icmp6 --icmpv6-type 129 -j ACCEPT
-A INPUT -p ipv6-icmp -m icmp6 --icmpv6-type 1 -j ACCEPT
-A INPUT -p ipv6-icmp -m icmp6 --icmpv6-type 3 -j ACCEPT
-A INPUT -p ipv6-icmp -m icmp6 --icmpv6-type 4 -j ACCEPT
-A INPUT -p ipv6-icmp -m icmp6 --icmpv6-type 2 -j ACCEPT
-A INPUT -p ipv6-icmp -m icmp6 --icmpv6-type 135 -j ACCEPT
-A INPUT -p ipv6-icmp -m icmp6 --icmpv6-type 136 -j ACCEPT
-A INPUT -j sshguard
-A INPUT -p tcp -m multiport --dports 22,25422 -m conntrack --ctstate NEW -j ACCEPT
-A INPUT -p tcp -m tcp --dport 873 -m conntrack --ctstate NEW -j ACCEPT
-A INPUT -p tcp -m tcp --dport 25443 -m conntrack --ctstate NEW -j ACCEPT
COMMIT

0
etc/fstab Normal file
View file

View file

@ -1,8 +0,0 @@
<?xml version="1.0"?>
<conf>
<main default="Slackware UK LDAP Server" logging="true" displayerrors="true" debuglevel="1024" templateCompileDirectory="/var/cache/fusiondirectory/template/" theme="breezy">
<location name="Slackware UK LDAP Server" forceSSL="true">
<referral URI="ldaps://core.slackware.uk.net:636" base="dc=slackware,dc=uk,dc=net" adminDn="cn=Administrator,cn=Users,dc=slackware,dc=uk,dc=net" adminPassword="rxdnq8cksunsa$0D" />
</location>
</main>
</conf>

Binary file not shown.

View file

@ -1,47 +1,53 @@
#!/bin/sh
#!/bin/bash
# Start/stop terraform-http-backend.
#
### BEGIN INIT INFO
# Provides: terraform-http-backend
# Required-Start: $network
# Required-Stop: $network
# Required-Start: $local_fs $remote_fs $network $syslog
# Required-Stop: $local_fs $remote_fs $network
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Terraform HTTP state backend daemon
# Description: Terraform HTTP state backend daemon
### END INIT INFO
# shellcheck disable=SC1091
NAME=terraform-http-backend
DAEMON=/opt/sbin/$NAME
NAME="terraform-http-backend"
DAEMON="/opt/sbin/$NAME"
DESC="Terraform HTTP state backend"
SCRIPT=terraform-http-backend
test -x $DAEMON || exit 0
[[ -x "$DAEMON" ]] || exit 0
[ -f /etc/default/terraform-http-backend ] && . /etc/default/terraform-http-backend
export TF_USER TF_IP TF_PORT TF_STORAGE_DIR TF_AUTH_ENABLED TF_USERNAME TF_PASSWORD
# shellcheck disable=SC2015
[[ -f /etc/default/terraform-http-backend ]] && . /etc/default/terraform-http-backend >/dev/null 2>&1 || {
echo "$0: error reading: /etc/default/terraform-http-backend"
exit 1
}
export TF_IP TF_PORT TF_STORAGE_DIR TF_AUTH_ENABLED TF_USERNAME TF_PASSWORD
. /lib/lsb/init-functions
case "$1" in
(start)
log_daemon_msg "Starting $DESC" $NAME
/usr/bin/su "$TF_USER" -c "$DAEMON >/dev/null 2>&1 &"
log_end_msg $?
start)
log_daemon_msg "Starting $DESC" "$NAME"
setpriv --keep-groups --reuid "${TF_USER:-root}" --regid "$(id -ng "${TF_USER:-root}")" -- "$DAEMON" >/dev/null 2>&1 &
log_end_msg "$?"
;;
(stop)
log_daemon_msg "Stopping $DESC" $NAME
/usr/bin/killall -TERM $DAEMON
log_end_msg $?
stop)
log_daemon_msg "Stopping $DESC" "$NAME"
killall -TERM "$DAEMON"
log_end_msg "$?"
;;
(restart|force-reload)
$0 stop && sleep 1 && $0 start
restart|force-reload)
"$0" stop
sleep 1
"$0" start
;;
(status)
status_of_proc $DAEMON $NAME && exit 0 || exit $?
status)
status_of_proc "$DAEMON" "$NAME" && exit 0 || exit "$?"
;;
(*)
echo "Usage: /etc/init.d/$SCRIPT {start|stop|restart|force-reload|status}"
*)
echo "Usage: $0 start|stop|restart|force-reload|status"
exit 1
;;
esac

View file

@ -1,8 +1,5 @@
[logging]
# FIXME:
# default = FILE:/var/log/krb5libs
# kdc = FILE:/var/log/krb5kdc
# admin_server = FILE:/var/log/kadmind
default = SYSLOG:WARNING:news
[libdefaults]
ccache_type = 4

25
etc/logrotate.conf Normal file
View file

@ -0,0 +1,25 @@
# Rotate log files on a monthly basis.
monthly
# Name files based upon the year/month they are rotated.
dateext
dateformat -%Y-%m
dateyesterday
# Compress rotated logs.
compress
# Keep 5 years of old logs (just to be sure).
rotate 60
# Move rotated logs to this directory.
olddir /var/log/Archived
# After rotating, create new (empty) files with the same owner/perms.
create
# E-mail logs which are about to be deleted to this address.
mail sysadmin@slackware.uk
# Read log specific configurations.
include /etc/logrotate.d

View file

@ -0,0 +1,4 @@
/var/log/alternatives.log {
missingok
notifempty
}

1
etc/logrotate.d/apache2 Normal file
View file

@ -0,0 +1 @@
# This file is intentionally empty to prevent new packages re-creating the original content.

15
etc/logrotate.d/apt Normal file
View file

@ -0,0 +1,15 @@
/var/log/apt/eipp.log.xz {
missingok
nocompress
notifempty
}
/var/log/apt/term.log {
missingok
notifempty
}
/var/log/apt/history.log {
missingok
notifempty
}

3
etc/logrotate.d/btmp Normal file
View file

@ -0,0 +1,3 @@
/var/log/btmp {
missingok
}

4
etc/logrotate.d/dpkg Normal file
View file

@ -0,0 +1,4 @@
/var/log/dpkg.log {
missingok
notifempty
}

View file

@ -0,0 +1 @@
# This file is intentionally empty to prevent new packages re-creating the original content.

View file

@ -0,0 +1,5 @@
/var/log/prometheus/prometheus.log {
copytruncate
notifempty
missingok
}

View file

@ -0,0 +1,5 @@
/var/log/prometheus/prometheus-alertmanager.log {
copytruncate
notifempty
missingok
}

View file

@ -0,0 +1,5 @@
/var/log/prometheus/prometheus-node-exporter.log {
copytruncate
notifempty
missingok
}

9
etc/logrotate.d/rsyslog Normal file
View file

@ -0,0 +1,9 @@
/var/log/auth /var/log/crond /var/log/messages /var/log/ftpd /var/log/kernel /var/log/dehydrated /var/log/smtpd /var/log/kerberos /var/log/named /var/log/samba/samba /var/log/rsyncd /var/log/php /var/log/httpd /var/log/ERROR /var/log/EMERG /var/log/DEBUG {
{
missingok
notifempty
sharedscripts
postrotate
/usr/lib/rsyslog/rsyslog-rotate
endscript
}

4
etc/logrotate.d/wtmp Normal file
View file

@ -0,0 +1,4 @@
/var/log/wtmp {
notifempty
missingok
}

4
etc/logrotate.d/wtmpdb Normal file
View file

@ -0,0 +1,4 @@
/var/log/wtmp.db {
notifempty
missingok
}

View file

@ -1 +1,9 @@
_ ... _
__ |-|-:__ ___. | , __ __ __ _ ___
(__` |``` __) / ` |.( | | __) |'` /___)
| .__) _|_ (__|_ '.__. _| \_ \_/\_/ (__|_ _|_ '.__.
| __ _ _ ,__
|___________________________________________ / / \ |_) |__
\__ \_/ | \ |__
Slackware UK Core Services

20
etc/pam.d/.gitignore vendored Normal file
View file

@ -0,0 +1,20 @@
/chfn
/chpasswd
/chsh
/common-account
/common-auth
/common-password
/common-session
/cron
/login
/newusers
/other
/passwd
/runuser
/runuser-l
/samba
/sshd
/su
/sudo
/sudo-i
/su-l

View file

@ -0,0 +1,29 @@
#
# /etc/pam.d/common-session-noninteractive - session-related modules
# common to all non-interactive services
#
# This file is included from other service-specific PAM config files,
# and should contain a list of modules that define tasks to be performed
# at the start and end of all non-interactive sessions.
#
# As of pam 1.0.1-6, this file is managed by pam-auth-update by default.
# To take advantage of this, it is recommended that you configure any
# local modules either before or after the default block, and use
# pam-auth-update to manage selection of other modules. See
# pam-auth-update(8) for details.
# here are the per-package modules (the "Primary" block)
session [default=1] pam_permit.so
# here's the fallback if no module succeeds
session requisite pam_deny.so
# prime the stack with a positive return value if there isn't one already;
# this avoids us returning an error just because nothing sets a success code
# since the modules above will each just jump around
session required pam_permit.so
# reset the umask for new sessions
session optional pam_umask.so
# Silence cron job messages in the authpriv log.
session [success=1 default=ignore] pam_succeed_if.so service in cron quiet use_uid
# and here are more per-package modules (the "Additional" block)
session required pam_unix.so
# end of pam-auth-update config

View file

@ -10,7 +10,7 @@ mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/bin/bash
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin

View file

@ -4,31 +4,20 @@ apache2-bin
apache2-data
apache2-utils
apt
apt-utils
attr
autoconf
automake
autopoint
autotools-dev
base-files
base-passwd
bash
bash-completion
bind9-dnsutils
bind9-host
bind9-libs
binutils
binutils-common
binutils-x86-64-linux-gnu
bsd-mailx
bootlogd
bsdextrautils
bsdutils
build-essential
bzip2
ca-certificates
coreutils
cpp
cpp-14
cpp-14-x86-64-linux-gnu
cpp-x86-64-linux-gnu
cron
cron-daemon-common
cronutils
@ -39,92 +28,57 @@ dbus-bin
dbus-daemon
dbus-session-bus-common
dbus-system-bus-common
dbus-user-session
debconf
debhelper
debian-archive-keyring
debianutils
dehydrated
dh-autoreconf
dh-strip-nondeterminism
dhcpcd-base
devuan-keyring
dialog
diffutils
dirmngr
distro-info-data
dokuwiki
dokuwiki-plugins-extra
dpkg
dpkg-dev
dummy-default-mta
dwz
equivs
fakeroot
file
findutils
fontconfig-config
fonts-dejavu-core
fonts-dejavu-mono
fonts-droid-fallback
fonts-noto-mono
fonts-urw-base35
freeipmi-common
fonts-glyphicons-halflings
fusiondirectory
fusiondirectory-integrator
fusiondirectory-schema
fusiondirectory-smarty3-acl-render
fusiondirectory-theme-oxygen
fusiondirectory-tools
g++
g++-14
g++-14-x86-64-linux-gnu
g++-x86-64-linux-gnu
gcc
gcc-14
gcc-14-base
gcc-14-x86-64-linux-gnu
gcc-x86-64-linux-gnu
gettext
gettext-base
ghostscript
git
git-man
gnupg
gnupg-l10n
gnupg-utils
gpg
gpg-agent
gpg-wks-client
gpgconf
gpgsm
gpgv
grep
groff-base
gsasl-common
gzip
hicolor-icon-theme
hostname
htop
ifupdown
imagemagick-7-common
init
inetutils-telnet
init-system-helpers
intltool-debian
ipmitool
initscripts
insserv
iproute2
ipset
iptables
iputils-ping
iso-codes
javascript-common
jq
kmod
krb5-config
krb5-locales
krb5-user
ldap-utils
less
libabsl20240722
libacl1
libalgorithm-diff-perl
libalgorithm-diff-xs-perl
libalgorithm-merge-perl
libaom3
libapache2-mod-php8.4
libapparmor1
@ -133,10 +87,7 @@ libaprutil1-dbd-sqlite3
libaprutil1-ldap
libaprutil1t64
libapt-pkg7.0
libarchive-cpio-perl
libarchive-zip-perl
libargon2-1
libasan8
libassuan9
libatomic1
libattr1
@ -146,7 +97,6 @@ libavahi-client3
libavahi-common-data
libavahi-common3
libavif16
libbinutils
libblkid1
libbpf1
libbrotli1
@ -154,100 +104,83 @@ libbsd0
libbz2-1.0
libc-bin
libc-client2007e
libc-dev-bin
libc-l10n
libc6
libc6-dev
libcap-ng0
libcap2
libcap2-bin
libcbor0.10
libcc1-0
libcom-err2
libcrypt-dev
libcrypt1
libctf-nobfd0
libctf0
libcups2t64
libcurl3t64-gnutls
libcurl4t64
libcurses-perl
libcurses-ui-perl
libdav1d7
libdb5.3t64
libdbus-1-3
libde265-0
libdebconfclient0
libdebhelper-perl
libdeflate0
libdialog15
libdpkg-perl
libduktape207
libedit2
libelf1t64
liberror-perl
libestr0
libeudev1
libexpat1
libfakeroot
libfastjson4
libffi8
libfftw3-double3
libfido2-1
libfile-fcntllock-perl
libfile-stripnondeterminism-perl
libfontconfig1
libfontenc1
libfreeipmi17
libfreetype6
libfstrm0
libgav1-1
libgcc-14-dev
libgcc-s1
libgcrypt20
libgd3
libgdbm-compat4t64
libgdbm6t64
libglib2.0-0t64
libglib2.0-data
libgmp10
libgnutls30t64
libgomp1
libgpg-error-l10n
libgpg-error0
libgpgme11t64
libgpm2
libgprofng0
libgs-common
libgs10
libgs10-common
libgsasl18
libgssapi-krb5-2
libgssglue1
libgssrpc4t64
libheif-plugin-aomenc
libheif-plugin-dav1d
libheif-plugin-libde265
libheif-plugin-x265
libheif1
libhogweed6t64
libhwasan0
libice6
libicu76
libidn12
libidn2-0
libijs-0.35
libimagequant0
libio-pty-perl
libip4tc2
libip6tc2
libipc-run-perl
libisl23
libitm1
libipset13t64
libjansson4
libjbig0
libjbig2dec0
libjemalloc2
libjpeg62-turbo
libjq1
libjs-bootstrap
libjs-bootstrap4
libjs-d3
libjs-eonasdan-bootstrap-datetimepicker
libjs-jquery
libjs-jquery-cookie
libjs-jquery-hotkeys
libjs-jquery-ui
libjs-moment
libjs-moment-timezone
libjs-mustache
libjs-popper.js
libjs-prototype
libjs-rickshaw
libjs-scriptaculous
libjson-c5
libk5crypto3
@ -255,91 +188,62 @@ libkadm5clnt-mit12
libkadm5srv-mit12
libkdb5-10t64
libkeyutils1
libkmod2
libkrb5-3
libkrb5support0
libksba8
liblastlog2-2
liblcms2-2
libldap-common
libldap2
libldb2
liblerc4
liblmdb0
liblocale-gettext-perl
liblockfile-bin
liblockfile1
liblognorm5
liblqr-1-0
liblsan0
libltdl-dev
libltdl7
liblua5.4-0
liblz4-1
liblzma5
libmagic-mgc
libmagic1t64
libmagickcore-7.q16-10
libmagickwand-7.q16-10
libmail-sendmail-perl
libmaxminddb0
libmd0
libmnl0
libmount1
libmpc3
libmpfr6
libncurses6
libncursesw6
libnetfilter-conntrack3
libnettle8t64
libnfnetlink0
libnftables1
libnftnl11
libnghttp2-14
libnghttp3-9
libngtcp2-16
libngtcp2-crypto-gnutls8
libnpth0t64
libnss-systemd
libnss-winbind
libntlm0
libnuma1
libnvme1t64
libodbc2
libonig5
libopenipmi0t64
libopenjp2-7
libp11-kit0
libpam-cap
libpam-modules
libpam-modules-bin
libpam-runtime
libpam-systemd
libpam-winbind
libpam0g
libpaper-utils
libpaper2
libpci3
libpcre2-8-0
libperl5.40
libpipeline1
libphp-simplepie
libpng16-16t64
libpolkit-agent-1-0
libpolkit-gobject-1-0
libpopt0
libpq5
libproc2-0
libprotobuf-c1
libpsl5t64
libpython3-stdlib
libpython3.13
libpython3.13-minimal
libpython3.13-stdlib
libquadmath0
libqdbm14t64
librav1e0.7
libraw23t64
libreadline8t64
librtmp1
libsasl2-2
libsasl2-modules
libsasl2-modules-db
libseccomp2
libsecret-1-0
@ -347,43 +251,29 @@ libsecret-common
libselinux1
libsemanage-common
libsemanage2
libsensors-config
libsensors5
libsepol2
libsframe1
libsharpyuv0
libsm6
libsmartcols1
libsnmp-base
libsnmp40t64
libsodium23
libsqlite3-0
libss2
libssh2-1t64
libssl3t64
libstdc++-14-dev
libstdc++6
libsvtav1enc2
libsys-hostname-long-perl
libsystemd-shared
libsystemd0
libtalloc2
libtasn1-6
libtdb1
libterm-readkey-perl
libtevent0t64
libtext-charwidth-perl
libtext-wrapi18n-perl
libtidy58
libtiff6
libtime-duration-perl
libtimedate-perl
libtinfo6
libtirpc-common
libtirpc3t64
libtool
libtsan2
libubsan1
libuchardet0
libudev1
libunistring5
liburcu8t64
liburing2
@ -397,7 +287,6 @@ libwrap0
libwtmpdb0
libx11-6
libx11-data
libx265-215
libxau6
libxcb1
libxdmcp6
@ -405,43 +294,28 @@ libxext6
libxml2
libxpm4
libxslt1.1
libxt6t64
libxtables12
libxxhash0
libyaml-0-2
libyuv0
libzstd1
linux-libc-dev
linux-sysctl-defaults
locales
locales-all
login
login.defs
logrotate
lsb-release
lynx
lynx-common
m4
mailcap
make
man-db
manpages
manpages-dev
mawk
media-types
mlock
moreutils
mount
msmtp
nano
ncurses-base
ncurses-bin
ncurses-term
net-tools
netbase
nftables
nvme-cli
openipmi
openssh-client
openssh-server
openssh-sftp-server
@ -450,7 +324,6 @@ openssl-provider-legacy
oxygen-icon-theme
passwd
patch
pci.ids
perl
perl-base
perl-modules-5.40
@ -459,14 +332,19 @@ php-bcmath
php-bz2
php-cas
php-common
php-constant-time
php-curl
php-fpdf
php-fpm
php-gd
php-geshi
php-gmp
php-intl
php-kissifrot-php-ixr
php-ldap
php-mbstring
php-phpseclib3
php-random-compat
php-sqlite3
php-xml
php-yaml
@ -476,6 +354,7 @@ php8.4-bz2
php8.4-cli
php8.4-common
php8.4-curl
php8.4-dba
php8.4-fpm
php8.4-gd
php8.4-gmp
@ -484,98 +363,57 @@ php8.4-imap
php8.4-intl
php8.4-ldap
php8.4-mbstring
php8.4-mysql
php8.4-odbc
php8.4-opcache
php8.4-pgsql
php8.4-readline
php8.4-soap
php8.4-sqlite3
php8.4-tidy
php8.4-xml
php8.4-yaml
php8.5-cli
php8.5-common
php8.5-phpdbg
php8.5-readline
php8.5-yaml
phpldapadmin
pinentry-curses
pkexec
po-debconf
polkitd
poppler-data
procps
prometheus
prometheus-alertmanager
prometheus-node-exporter
prometheus-node-exporter-collectors
promtool
psmisc
publicsuffix
python-apt-common
python3
python3-anyio
python3-apt
python3-bcrypt
python3-certifi
python3-cffi-backend
python3-click
python3-cryptography
python3-decorator
python3-dnspython
python3-gpg
python3-h11
python3-h2
python3-hpack
python3-httpcore
python3-httpx
python3-hyperframe
python3-idna
python3-ldb
python3-linkify-it
python3-markdown
python3-markdown-it
python3-mdurl
python3-minimal
python3-prometheus-client
python3-pygments
python3-rich
python3-samba
python3-sniffio
python3-talloc
python3-tdb
python3-uc-micro
python3-yaml
python3.13
python3.13-minimal
readline-common
rpcsvc-proto
rsync
rsyslog
runit-helper
s-nail
samba
samba-ad-dc
samba-ad-provision
samba-common
samba-common-bin
samba-dsdb-modules
samba-libs
sed
sensible-utils
sgml-base
shared-mime-info
shellcheck
smarty-gettext
smarty3
sqv
sshguard
ssl-cert
startpar
sudo
systemd
systemd-resolved
systemd-sysv
systemd-standalone-sysusers
systemd-standalone-tmpfiles
sysv-rc
sysv-rc-conf
sysvinit-core
sysvinit-utils
tar
tdb-tools
telnet
tzdata
ucf
udev
util-linux
uuid-runtime
vim
vim-common
vim-runtime
winbind
x11-common
xdg-user-dirs
xfonts-encodings
xfonts-utils
xml-core
xz-utils
vim-tiny
wget
zlib1g

8
etc/rc.local Executable file
View file

@ -0,0 +1,8 @@
#!/bin/bash
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other value on error.
# In order to enable or disable this script just change the execution bits.
[[ -d /etc/boot.d ]] && run-parts /etc/boot.d
exit 0

8
etc/rc.shutdown Executable file
View file

@ -0,0 +1,8 @@
#!/bin/bash
# This script is executed by /etc/init.d/rc.local stop.
# Make sure that the script will "exit 0" on success or any other value on error.
# In order to enable or disable this script just change the execution bits.
[[ -d /etc/shutdown.d ]] && run-parts /etc/shutdown.d
exit 0

View file

@ -1,6 +1,8 @@
options timeout:2
options edns0
search slackware.uk.net
nameserver 5.101.171.216
nameserver 5.101.171.217
nameserver 185.176.90.169
# FIXME:
#nameserver 5.101.171.216
#nameserver 5.101.171.217
#nameserver 185.176.90.169
nameserver 8.8.8.8

9
etc/rsyncd.banner Normal file
View file

@ -0,0 +1,9 @@
_ ... _
__ |-|-:__ ___. | , __ __ __ _ ___
(__` |``` __) / ` |.( | | __) |'` /___)
| .__) _|_ (__|_ '.__. _| \_ \_/\_/ (__|_ _|_ '.__.
| __ _ _ ,__
|___________________________________________ / / \ |_) |__
\__ \_/ | \ |__
Slackware UK Core Services

89
etc/rsyncd.conf Normal file
View file

@ -0,0 +1,89 @@
# Connecting
# Note: Either an IPv4 OR IPv6 address can be used here, not both. Default: bind to all IPs.
#address =
max connections = 10
timeout = 30
motd file = /etc/rsyncd.banner
# Daemon security
uid = mirror
gid = mirror
use chroot = true
read only = false
write only = true
list = false
secrets file = /etc/rsyncd.passwd
exclude = .rsync-tmp/*** .zfs/***
# Logging
syslog facility = local5
#log file = /var/log/rsyncd
#transfer logging = true
pid file = /run/rsyncd.pid
# Daemon behaviour
incoming chmod = u+w,go-w,Dugo+rx,Fugo+rX
refuse options = backup backup-dir inplace append append-verify acls xattrs chmod super fake-super rsync-path ignore-errors compress-level blocking-io iconv checksum-seed
dont compress = *.7z *.[bglx]z *.aac *.arj *.avi *.bz2 *.deb *.dpkg *.flac *.flv *.gif *.giff *.iso *.jpeg *.jpg *.lha *.lzh *.lzma *.m[34][av] *.mkv *.mov *.mp[34] *.mp[34][av] *.mpeg *.mpg *.og[agvx] *.qt *.rar *.rpm *.srpm *.t[bglx]z *.tz *.vob *.wm[av] *.z *.zip
post-xfer exec = /opt/bin/notify-rsync-upload
[bonappetit-upload]
path = /data/mirrors/bonappetit
auth users = bonappetit
[csb-upload]
path = /data/mirrors/csb
auth users = willysr
[msb-upload]
path = /data/mirrors/msb
auth users = willysr
[people-n4t3r-upload]
path = /data/mirrors/people/n4t3r
auth users = nate
[sarpi-upload]
path = /data/mirrors/sarpi
auth users = exaga
[slackdce-upload]
path = /data/mirrors/slackdce
auth users = lu9dce
[slackel-upload]
path = /data/mirrors/slackel
auth users = djemos
[slackvirt-upload]
path = /data/mirrors/slackvirt
auth users = megalnx
[slackwarearm-upload]
path = /data/mirrors/slackwarearm
auth users = mozes
[slackwarearm-people-brent-upload]
path = /data/mirrors/slackwarearm/people/brent
auth users = brent
[slackwarearm-people-louigi600-upload]
path = /data/mirrors/slackwarearm/people/louigi600
auth users = louigi600
[slackwareloong-upload]
path = /data/mirrors/slackwareloong
auth users = shipujin
[slint-upload]
path = /data/mirrors/slint
auth users = billyw hunterj tomm tonys
[smlinux-upload]
path = /data/mirrors/smlinux
auth users = skyroverr
[tmp-upload]
path = /data/tmp/rsync-upload
auth users = guest

6
etc/rsyncd.passwd.gpg Normal file
View file

@ -0,0 +1,6 @@
Œ  
AlÍ*¢ÿÒÀç È<C2A0>ƲÌI$!!Ã'òwÛήQWø#"“kæ¨k…„®˜#ëDX˜FáHöWøP(9­íÃ<52>¥—RöNUÊ3 ÷ÈO••à†Z§ècÐ=ßÓ"×ä&cüùIpÀy7 
ò<EFBFBD>óªyl:²ð¦¸°¡Þàdè
>Mª•UËÙ!L{€A°],‹²“>ÜrŽë6ŸI`: îÀXŸ7m]e³Ê®è̘4•ŒEÿòª«Íd°®N
‰ç"yš†éFó䦵M¤™ÆSAáI{z»ô0<E282AC><E28098>ç¦<í6»2—/À{yûL©ÿ»ÓÕÝâr€ôYy1üìA39\~(³Ñ&Û»<C39B>¸ØZ*w]U¼^za ËšÖ ÍWMs$Âð¨8gätn)g¼¿©¸-NóBwøþz8"‡‡q«F-}>±¯ž>¼² y«9/ýè\o]…5<E280A6><Ýšz?˜Ùf ïvVmã½:„íXTÌ;ußÊVI«X
+žè½ÿ+ˆeV™Òew?Gº

View file

@ -1,143 +1,180 @@
# VMWare: RFC5424 message format.
# Load modules.
module(load="imuxsock" sysSock.usePIDFromSystem="on")
module(load="imudp")
module(load="imtcp")
module(load="builtin:omfile" dirCreateMode="0750" dirOwnerNum="0" dirGroupNum="0" fileCreateMode="0640" fileOwnerNum="0" fileGroupNum="0" compression.driver="zstd")
module(load="imfile" Mode="inotify")
module(load="builtin:omfile" dirCreateMode="0755" dirOwnerNum="0" dirGroupNum="0" fileCreateMode="0644" fileOwnerNum="0" fileGroupNum="0" compression.driver="zstd")
# Global configuration.
global(
workDirectory="/var/lib/rsyslog"
workDirectory="/var/spool/rsyslog"
#stdlog.channelspec="on"
maxMessageSize="16K"
senders.keepTrack="on"
senders.timeoutAfter="2419200"
senders.reportGoneAway="on"
senders.reportNew="on"
parser.permitSlashInProgramName="on"
)
# Inputs.
input(type="imudp" port="25414" ruleset="syslog")
input(type="imudp" port="25415" ruleset="httplog")
input(type="imtcp" port="25414" ruleset="syslog")
# Templates.
# For the log lines.
# The format for any version of message received is:
# <date> <short-hostname> <facility>.<severity> <msgid> <tag> <message>
# Where <msgid> may be '-' for none, and <tag> is either the message's "tag", "app-name", or '-' for none.
template(name="localLogLine" type="string" string="%timereported% %$.host% %syslogfacility-text%.%syslogseverity-text% %$.id% %$.tag%%msg:::sp-if-no-1st-sp%%msg:::escape-cc,drop-last-lf%\n")
template(name="centralLogLine" type="string" string="%timereported:::date-utc% %$.host% %syslogfacility-text%.%syslogseverity-text% %$.id% %$.tag%%msg:::sp-if-no-1st-sp%%msg:::escape-cc,drop-last-lf%\n")
# For the logfile locations.
template(name="localFile" type="string" string="/var/log/%$.logfile%")
template(name="centralFile" type="string" string="/data/logs/%$.fqdn%/%timegenerated:1:4:date-utc,date-rfc3339%/%timegenerated:6:7:date-utc,date-rfc3339%/%timegenerated:9:10:date-utc,date-rfc3339%/%$.logfile%")
# Rulesets.
ruleset(name="syslog") {
set $.host = tolower(field($hostname, ".", 1));
set $.domain = tolower(re_extract($hostname, '[^.]+\\.(.*)', 0, 1, "unknown_domain"));
if ($app-name != "") then {
set $.proc = $app-name;
if ($procid != "" and $procid != "-") then {
set $.proc = '[' & $procid & ']';
}
# Rulesets. Must be defined before inputs that use them.
ruleset(name="localSyslog") {
# Use the host's lowercased FQDN.
set $.fqdn = tolower("core.slackware.uk.net");
# Extract the hostname part of the FQDN the message was receieved from.
set $.host = field($.fqdn, ".", 1);
# Hack for RFC3164 messages that do not contain a 'tag' (usually the process name and ID ending in :).
if ($syslogtag == "") then {
set $.tag = "-:";
} else {
set $.proc = '-';
set $.tag = $syslogtag;
}
if ($msgid != "") then {
# Hack for messages that do not contain a 'msgid'.
if ($msgid == "") then {
set $.id = "-";
} else {
set $.id = $msgid;
}
# Direct the message to the correct log(s).
if prifilt("auth.*,authpriv.*") then set $.logfile = "auth";
if prifilt("cron.*") then set $.logfile = "crond";
if prifilt("daemon.*,syslog.*,user.*,uucp.*,local0.*,local1.*,local2.*") then set $.logfile = "messages";
if prifilt("ftp.*") then set $.logfile = "ftpd";
if prifilt("kern.*") then set $.logfile = "kernel";
if prifilt("lpr.*") then set $.logfile = "dehydrated";
if prifilt("mail.*") then set $.logfile = "smtpd";
if prifilt("news.*") then set $.logfile = "kerberos";
if prifilt("local3.*") then set $.logfile = "named";
# FIXME: Correct logfile for samba?
if prifilt("local4.*") then set $.logfile = "samba/samba";
if prifilt("local5.*") then set $.logfile = "rsyncd";
if prifilt("local6.*") then set $.logfile = "php";
if prifilt("local7.*") then set $.logfile = "httpd";
# For next release of rsyslog:
# set $.ret = parse_json('[]', "\$!logfiles");
# if prifilt("auth.*,authpriv.*") then set $!logfiles = append_json($!logfiles, "auth");
# if prifilt("cron.*") then set $!logfiles = append_json($!logfiles, "crond");
# if prifilt("daemon.*,syslog.*,user.*,uucp.*,local0.*,local1.*,local2.*") then set $!logfiles = append_json($!logfiles, "messages");
# if prifilt("ftp.*") then set $!logfiles = append_json($!logfiles, "ftpd");
# if prifilt("kern.*") then set $!logfiles = append_json($!logfiles, "kernel");
# if prifilt("lpr.*") then set $!logfiles = append_json($!logfiles, "dehydrated");
# if prifilt("mail.*") then set $!logfiles = append_json($!logfiles, "smtpd");
# if prifilt("news.*") then set $!logfiles = append_json($!logfiles, "kerberos");
# if prifilt("local3.*") then set $!logfiles = append_json($!logfiles, "named");
# if prifilt("local4.*") then set $!logfiles = append_json($!logfiles, "samba/samba");
# if prifilt("local5.*") then set $!logfiles = append_json($!logfiles, "rsyncd");
# if prifilt("local6.*") then set $!logfiles = append_json($!logfiles, "php");
# if prifilt("local7.*") then set $!logfiles = append_json($!logfiles, "httpd");
# if prifilt("*.err,*.crit') then set $!logfiles = append_json($!logfiles, "ERROR");
# if prifilt("*.alert,*.emerg') then set $!logfiles = append_json($!logfiles, "EMERG");
# if prifilt("*.debug") then set $!logfiles = append_json($!logfiles, "DEBUG");
# Write the logs.
# foreach ($.logfile in $!logfiles) do {
action(type="omfile" dynaFile="localFile" template="localLogLine" asyncWriting="on" flushInterval="5" ioBufferSize="64k" createDirs="on")
action(type="omfile" dynaFile="centralFile" template="centralLogLine" asyncWriting="on" flushInterval="5" ioBufferSize="64k" createDirs="on")
# }
}
ruleset(name="remoteSyslog") {
# Use the incoming host's lowercased FQDN.
set $.fqdn = tolower($fromhost);
# Extract the hostname part of the FQDN the message was receieved from.
set $.host = field($.fqdn, ".", 1);
# Hack for RFC5424 messages that do not contain an app-name or procid.
if ($app-name == "") then {
if ($syslogtag == "") then {
set $.tag = "-";
} else {
set $.id = '-';
set $.tag = $syslogtag;
}
template(name="LogLineSingleHost" type="string" string="%timereported:::date-utc,date-rfc3339% %$.host% %pri-text% %$.proc% %$.id% :%msg:::sp-if-no-1st-sp%%msg:::escape-cc,drop-last-lf%\n")
template(name="LogLineAllHosts" type="string" string="%timereported:::date-utc,date-rfc3339% %hostname% %pri-text% %$.proc% %$.id% :%msg:::sp-if-no-1st-sp%%msg:::escape-cc,drop-last-lf%\n")
# FIXME: Log each facility to the AllHosts logs. Compression?
if prifilt("auth.*,authpriv.*") then {
action(type="omfile" file="/tmp/log/AllHosts/auth" template="LogLineAllHosts" zipLevel="6" asyncWriting="on" flushInterval="5" ioBufferSize="64k" )
} else if ... then {
template(name="LogFileeSingleHost" type="string" string="/tmp/logs/%$.host%/
%timereported:::date-utc,date-rfc3339% %$.host% %pri-text% %$.proc% %$.id% :%msg:::sp-if-no-1st-sp%%msg:::escape-cc,drop-last-lf%\n")
if prifilt("*.info") then {
action(type="omfile" file="/var/log/info.log")
} else {
if ($procid == "") then {
set $.tag = $app-name;
} else {
set $.tag = $app-name & '[' & $procid & ']';
}
}
# Hack for messages that do not contain a 'msgid'.
if ($msgid == "") then {
set $.id = "-";
} else {
set $.id = $msgid;
}
# Direct the message to the correct log(s).
if (re_match_i($.host, '^(esx[[:alnum:]]|vcsa)$')) then {
if prifilt("auth.*,authpriv.*") then set $.logfile = "auth";
if prifilt("cron.*,daemon.*,ftp.*,lpr.*,news.*,syslog.*,user.*,uucp.*,local0.*,local1.*,local2.*,local3.*,local4.*,local5.*,local6.*,local7.*") then set $.logfile = "messages";
if prifilt("kern.*") then set $.logfile = "kernel";
if prifilt("mail.*") then set $.logfile = "mail";
# For next release of rsyslog:
# if prifilt("auth.*,authpriv.*") then set $!logfiles = append_json($!logfiles, "auth");
# if prifilt("cron.*,daemon.*,ftp.*,lpr.*,news.*,syslog.*,user.*,uucp.*,local0.*,local1.*,local2.*,local3.*,local4.*,local5.*,local6.*,local7.*") then set $!logfiles = append_json($!logfiles, "messages");
# if prifilt("kern.*") then set $!logfiles = append_json($!logfiles, "kernel");
# if prifilt("mail.*,authpriv.*") then set $!logfiles = append_json($!logfiles, "mail");
# if prifilt("*.err,*.crit') then set $!logfiles = append_json($!logfiles, "ERROR");
# if prifilt("*.alert,*.emerg') then set $!logfiles = append_json($!logfiles, "EMERG");
# if prifilt("*.debug") then set $!logfiles = append_json($!logfiles, "DEBUG");
} else {
if prifilt("auth.*,authpriv.*") then set $.logfile = "auth";
if prifilt("cron.*") then set $.logfile = "crond";
if prifilt("daemon.*,syslog.*,user.*,uucp.*,local0.*,local1.*,local2.*") then set $.logfile = "messages";
if prifilt("ftp.*") then set $.logfile = "ftpd";
if prifilt("kern.*") then set $.logfile = "kernel";
if prifilt("lpr.*") then set $.logfile = "dehydrated";
if prifilt("mail.*") then set $.logfile = "smtpd";
if prifilt("news.*") then set $.logfile = "kerberos";
if prifilt("local3.*") then set $.logfile = "named";
if prifilt("local4.*") then set $.logfile = "samba/samba";
if prifilt("local5.*") then set $.logfile = "rsyncd";
if prifilt("local6.*") then set $.logfile = "php";
if prifilt("local7.*") then set $.logfile = "httpd";
# For next release of rsyslog:
# set $.ret = parse_json('[]', "\$!logfiles");
# if prifilt("auth.*,authpriv.*") then set $!logfiles = append_json($!logfiles, "auth");
# if prifilt("cron.*") then set $!logfiles = append_json($!logfiles, "crond");
# if prifilt("daemon.*,syslog.*,user.*,uucp.*,local0.*,local1.*,local2.*") then set $!logfiles = append_json($!logfiles, "messages");
# if prifilt("ftp.*") then set $!logfiles = append_json($!logfiles, "ftpd");
# if prifilt("kern.*") then set $!logfiles = append_json($!logfiles, "kernel");
# if prifilt("lpr.*") then set $!logfiles = append_json($!logfiles, "dehydrated");
# if prifilt("mail.*") then set $!logfiles = append_json($!logfiles, "smtpd");
# if prifilt("news.*") then set $!logfiles = append_json($!logfiles, "kerberos");
# if prifilt("local3.*") then set $!logfiles = append_json($!logfiles, "named");
# if prifilt("local4.*") then set $!logfiles = append_json($!logfiles, "samba/samba");
# if prifilt("local5.*") then set $!logfiles = append_json($!logfiles, "rsyncd");
# if prifilt("local6.*") then set $!logfiles = append_json($!logfiles, "php");
# if prifilt("local7.*") then set $!logfiles = append_json($!logfiles, "httpd");
# if prifilt("*.err,*.crit') then set $!logfiles = append_json($!logfiles, "ERROR");
# if prifilt("*.alert,*.emerg') then set $!logfiles = append_json($!logfiles, "EMERG");
# if prifilt("*.debug") then set $!logfiles = append_json($!logfiles, "DEBUG");
}
#template(name="SyslogLineFormat" type="list") {
# property(name="timereported" dateFormat="rfc3339" caseConversion="lower") # Timestamp yyyy-MM-dd'T'HH:mm:ss.SSS'Z'
# constant(value=" ")
# property(name="hostname") # Hostname
# constant(value=" ")
# property(name="syslogfacility") # Facility
# constant(value=".")
# property(name="syslogpriority") # Log priority
# constant(value=" ")
# property(name="syslogtag") # Syslog tag
# constant(value=": ")
# property(name="msg") # Message content
# constant(value="\n")
# Write the logs.
# foreach ($.logfile in $!logfiles) do {
action(type="omfile" dynaFile="centralFile" template="centralLogLine" asyncWriting="on" flushInterval="5" ioBufferSize="64k" createDirs="on")
# }
}
#template(name="LogHostFile" type="string" string="/mnt/Data/logs/%HOSTNAME:::escape-cc,secpath-replace%/
#%TIMESTAMP:::date-utc,date-year%/%TIMESTAMP:::date-utc,date-month%/%TIMESTAMP:::date-utc,date-day%/
# %syslogtag%%msg:::sp-if-no-1st-sp%%msg:::drop-last-lf%\n")
#template(name="LogAllHostsFile" type="string" string="/mnt/Data/logs/AllHosts/
#%TIMESTAMP:::date-utc,date-year%/%TIMESTAMP:::date-utc,date-month%/%TIMESTAMP:::date-utc,date-day%/
# %syslogtag%%msg:::sp-if-no-1st-sp%%msg:::drop-last-lf%\n")
#VMWare: RFC 5424
# Parser.
#parser(
# name="FIXME"
# type="pmnormalize"
# rule=[
# "rule=:<%pri:number%> %fromhost-ip:ipv4% %hostname:word% %syslogtag:char-to:\\x3a%: %msg:rest%",
# "rule=:<%pri:number%> %hostname:word% %fromhost-ip:ipv4% %syslogtag:char-to:\\x3a%: %msg:rest%"
# ]
#)
# Rules
#ruleset(name="outp" parser="custom.pmnormalize") {
# action(type="omfile" File="/tmp/output")
#}
# Outputs.
action(type="omfile" file="/tmp/messages" template="LogLineSingleHost")
# Inputs.
input(type="imuxsock" socket="/dev/log" usePIDFromSystem="on" ruleset="localSyslog")
input(type="imudp" port="25414" ruleset="remoteSyslog")
input(type="imtcp" port="25414" ruleset="remoteSyslog")
# Include additional configurations.
include(file="/etc/rsyslog.d/*.conf" mode="optional")
### Examples ####
# Send all logs to remote syslog via UDP.
# An on-disk queue is created for this action. If the remote host is
# down, messages are spooled to disk and sent when it is up again.
#*.* action(
# type="omfwd"
# target="192.168.0.1"
# port="514"
# protocol="udp"
# queue.filename="fwdRule1" # unique name prefix for spool files
# queue.type="LinkedList"
# queue.maxDiskSpace="256m"
# queue.saveOnShutdown="on"
# action.resumeRetryCount="-1"
# action.resumeInterval="30"
#)

107
etc/s-nail.rc Normal file
View file

@ -0,0 +1,107 @@
# Do not move messages from the system mailbox to a local mbox.
set hold
# Messages will be appended (rather than prepended) to mboxes.
# This should usually always be set.
# This has no effect unless 'hold' is unset again.
set append
# Always ask for a subject when composing a message interactively.
set ask
# Assume a CRT-like terminal and invoke a pager.
set crt
# Messages may be terminated by a dot.
set dot
# Do not remove empty mail folders in the spool directory.
# This may be relevant for privacy since other users could
# otherwise create them with different permissions.
set keep
# Do not remove empty mail folders.
set emptybox
# Quote the original message in replies by "> " as usual on the Internet.
set indentprefix="> "
# Automatically quote the text of the message that is responded to.
set quote
# Outgoing messages are sent in UTF-8 if possible, otherwise LATIN1.
set sendcharsets=utf-8,iso-8859-1
# Display sender's real names in header summaries.
set showname
# Display the recipients of messages sent by the user himself in
# header summaries.
set showto
# Automatically check for new messages at each prompt, but avoid polling
# of IMAP servers or maildir folders.
set newmail=nopoll
# If threaded mode is activated, automatically collapse thread.
set autocollapse
# Mark messages that have been answered.
set markanswered
# Hide some header fields which are uninteresting for most human readers.
ignore received in-reply-to message-id references
ignore mime-version content-transfer-encoding
# Only include selected header fields when forwarding messages.
headerpick forward retain subject date from to cc
# Use a directory named 'mail' in the users homedir to hold mailboxes.
set folder=mail/
# Keep the comment/name part of email addresses when replying.
set fullnames
# Use 'less' for paged output.
set PAGER=/usr/bin/less
# When spawning an editor in compose mode, allow editing of headers.
set editheaders
# Startup into interactive mode even if the (given) mailbox is empty.
set emptystart
# Add more entries to the history as is done by default.
# The latter will cause the built-in editor to save those entries, too.
set history-gabby all history-gabby-persist
# Try to circumvent false or missing MIME Content-Type descriptions.
# Do set a value for extended behaviour (see the manual).
#set mime-counter-evidence
set mime-counter-evidence=0b1111
# Do not move `save'd or `write'n message to $MBOX by default since this is
# likely to be irritating for most users today.
set keepsave
# When replying, do not merge From: and To: of the original message
# into To:. Instead old From: -> new To:, old To: -> merge Cc:.
set recipients-in-cc
# Whether a Mail-Followup-To: header is honoured when group-replying.
set followup-to-honour=ask-yes
# Whether a Reply-To: header is honoured when replying.
set reply-to-honour=ask-yes
# When sending a message, wait until the MTA (including the built-in SMTP one)
# exits before accepting further commands. Only with this variable set are
# errors reported by the MTA recognised!
set sendwait
# Only include these selected header fields when printing messages.
retain date sender from to cc subject message-id mail-followup-to reply-to
# Use an SMTP server rather than 'sendmail' to deliver mail.
# Set to the IP/Name of an SMTP server which will accept mail from this host.
# set smtp=mail.example.com

Binary file not shown.

4
etc/shutdown.d/pushover-alert Executable file
View file

@ -0,0 +1,4 @@
#!/bin/bash
# Alert that this host is going down.
[[ -x /opt/sbin/pushover-client ]] && /opt/sbin/pushover-client -p -1 -m "Shut down: ${HOSTNAME%%.*}"

1
etc/sshguard/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
/blacklist

View file

@ -2,10 +2,10 @@
# sshguard.conf -- SSHGuard configuration
# Full path to backend executable (required, no default)
BACKEND="/usr/libexec/sshg-fw-iptables"
BACKEND="/usr/libexec/sshguard/sshg-fw-iptables"
# Space-separated list of log files to monitor. (optional, no default)
FILES="/var/log/core.slackware.uk.net/auth"
FILES="/var/log/auth"
# Shell command that provides logs on standard output. (optional, no default)
# Example 1: ssh and sendmail from systemd journal:
@ -26,21 +26,21 @@ BLOCK_TIME=86400
DETECTION_TIME=28800
# Size of IPv6 subnet to block. Defaults to a single address, CIDR notation. (optional, default to 128)
IPV6_SUBNET=128
IPV6_SUBNET=64
# Size of IPv4 subnet to block. Defaults to a single address, CIDR notation. (optional, default to 32)
IPV4_SUBNET=32
IPV4_SUBNET=24
# Full path to PID file (optional, no default)
PID_FILE=/run/sshguard.pid
# Colon-separated blacklist threshold and full path to blacklist file.
# (optional, no default)
BLACKLIST_FILE=10:/var/lib/sshguard/blacklist
BLACKLIST_FILE=10:/etc/sshguard/blacklist
# IP addresses listed in the WHITELIST_FILE are considered to be
# friendlies and will never be blocked.
WHITELIST_FILE=/etc/sshguard.whitelist
WHITELIST_FILE=/etc/sshguard/whitelist
# If PARSER is unset, SSHGuard will use the installed sshg-parser as its
# parser. Setting PARSER overrides this, so that you can use your own parser.

View file

@ -1,56 +0,0 @@
#!/bin/bash
# Default configuration.
LOGS_DIR="/var/log"
DIR_MODE="0750"
UMASK="027"
# This array may be used in the defaults file.
declare -A CREATE_DIRS
# Allow /etc/default/rotate-logs-symlinks to override default configuration.
[[ -e /etc/default/rotate-logs-symlinks ]] && {
# shellcheck disable=SC1091
source /etc/default/rotate-logs-symlinks || {
printf "%s: %s\\n" "${0##*/}" "failed reading /etc/default/rotate-logs-symlinks" >&2
exit 1
}
}
# Process the directories in the logs directory.
[[ -d "$LOGS_DIR" ]] && {
TODAY="$(printf "%(%Y/%m/%d)T")"
umask "$UMASK"
# Process all the directories in the logs directory.
for DIR in "$LOGS_DIR"/*/; do
cd "$DIR" 2>/dev/null || {
printf "%s: %s\\n" "${0##*/}" "failed to change directory to '$DIR'" >&2
continue
}
# Create a new logs directory for today.
# shellcheck disable=SC2174
mkdir -p -m "$DIR_MODE" "$TODAY" 2>/dev/null || {
printf "%s: %s\\n" "${0##*/}" "failed to create directory '$DIR/$TODAY'" >&2
continue
}
# If configured to do so for this directory, create sub directories.
for CREATE_DIR in ${CREATE_DIRS[$(printf "$DIR" | awk -F / -e '{print $4}')]}; do
mkdir -p -m "$DIR_MODE" "$TODAY/$CREATE_DIR" 2>/dev/null || {
printf "%s: %s\\n" "${0##*/}" "failed to create directory '$DIR/$TODAY/$CREATE_DIR'" >&2
continue
}
done
# Create a 'today' symlink to the new days' directory.
( cd "$DIR" 2>/dev/null && ln -sfn "$TODAY" "today" 2>/dev/null ) || {
printf "%s: %s\\n" "${0##*/}" "updating 'today' symlink failed" >&2
continue
}
done
}
exit 0

View file

@ -0,0 +1,24 @@
#!/bin/bash
# Default configuration.
LOGS_DIR="/data/logs"
# Process the directories in the $LOGS_DIR directory.
[[ -d "$LOGS_DIR" ]] && {
TODAY="$(printf "%(%Y/%m/%d)T")"
for DIR in "$LOGS_DIR"/*/; do
cd "$DIR" 2>/dev/null || {
printf "%s: %s\\n" "${0##*/}" "failed to change directory to '$DIR'" >&2
continue
}
# Create the 'today' symlink to the new location..
ln -sfn "$TODAY" "today" 2>/dev/null || {
printf "%s: %s\\n" "${0##*/}" "updating 'today' symlink failed in '$DIR'" >&2
continue
}
done
}
exit 0

View file

@ -14,7 +14,7 @@ case "$ID" in
'alpine')
apk list -I | cut -d' ' -f1 | rev | cut -d- -f3- | rev >/etc/pkglist
;;
'debian'|'ubuntu')
'debian'|'devuan'|'ubuntu')
dpkg-query --show --showformat='${Package}\n' >/etc/pkglist
;;
'slackware')

View file

@ -1,2539 +0,0 @@
#!/usr/bin/env bash
# dehydrated by lukas2511
# Source: https://dehydrated.io
#
# This script is licensed under The MIT License (see LICENSE for more information).
set -e
set -u
set -o pipefail
[[ -n "${ZSH_VERSION:-}" ]] && set -o SH_WORD_SPLIT && set +o FUNCTION_ARGZERO && set -o NULL_GLOB && set -o noglob
[[ -z "${ZSH_VERSION:-}" ]] && shopt -s nullglob && set -f
umask 077 # paranoid umask, we're creating private keys
# Close weird external file descriptors
exec 3>&-
exec 4>&-
VERSION="0.7.3"
# Find directory in which this script is stored by traversing all symbolic links
SOURCE="${0}"
while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
SOURCE="$(readlink "$SOURCE")"
[[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
done
SCRIPTDIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
BASEDIR="${SCRIPTDIR}"
ORIGARGS=("${@}")
noglob_set() {
if [[ -n "${ZSH_VERSION:-}" ]]; then
set +o noglob
else
set +f
fi
}
noglob_clear() {
if [[ -n "${ZSH_VERSION:-}" ]]; then
set -o noglob
else
set -f
fi
}
# Generate json.sh path matching string
json_path() {
if [ ! "${1}" = "-p" ]; then
printf '"%s"' "${1}"
else
printf '%s' "${2}"
fi
}
# Get string value from json dictionary
get_json_string_value() {
local filter
filter="$(printf 's/.*\[%s\][[:space:]]*"\([^"]*\)"/\\1/p' "$(json_path "${1:-}" "${2:-}")")"
sed -n "${filter}"
}
# Get array values from json dictionary
get_json_array_values() {
grep -E '^\['"$(json_path "${1:-}" "${2:-}")"',[0-9]*\]' | sed -e 's/\[[^\]*\][[:space:]]*//g' -e 's/^"//' -e 's/"$//'
}
# Get sub-dictionary from json
get_json_dict_value() {
local filter
filter="$(printf 's/.*\[%s\][[:space:]]*\(.*\)/\\1/p' "$(json_path "${1:-}" "${2:-}")")"
sed -n "${filter}" | jsonsh
}
# Get integer value from json
get_json_int_value() {
local filter
filter="$(printf 's/.*\[%s\][[:space:]]*\([^"]*\)/\\1/p' "$(json_path "${1:-}" "${2:-}")")"
sed -n "${filter}"
}
# Get boolean value from json
get_json_bool_value() {
local filter
filter="$(printf 's/.*\[%s\][[:space:]]*\([^"]*\)/\\1/p' "$(json_path "${1:-}" "${2:-}")")"
sed -n "${filter}"
}
# JSON.sh JSON-parser
# Modified from https://github.com/dominictarr/JSON.sh
# Original Copyright (c) 2011 Dominic Tarr
# Licensed under The MIT License
jsonsh() {
throw() {
echo "$*" >&2
exit 1
}
awk_egrep () {
local pattern_string=$1
awk '{
while ($0) {
start=match($0, pattern);
token=substr($0, start, RLENGTH);
print token;
$0=substr($0, start+RLENGTH);
}
}' pattern="$pattern_string"
}
tokenize () {
local GREP
local ESCAPE
local CHAR
if echo "test string" | grep -Eao --color=never "test" >/dev/null 2>&1
then
GREP='grep -Eao --color=never'
else
GREP='grep -Eao'
fi
# shellcheck disable=SC2196
if echo "test string" | grep -Eao "test" >/dev/null 2>&1
then
ESCAPE='(\\[^u[:cntrl:]]|\\u[0-9a-fA-F]{4})'
CHAR='[^[:cntrl:]"\\]'
else
GREP=awk_egrep
ESCAPE='(\\\\[^u[:cntrl:]]|\\u[0-9a-fA-F]{4})'
CHAR='[^[:cntrl:]"\\\\]'
fi
local STRING="\"$CHAR*($ESCAPE$CHAR*)*\""
local NUMBER='-?(0|[1-9][0-9]*)([.][0-9]*)?([eE][+-]?[0-9]*)?'
local KEYWORD='null|false|true'
local SPACE='[[:space:]]+'
# Force zsh to expand $A into multiple words
local is_wordsplit_disabled
is_wordsplit_disabled="$(unsetopt 2>/dev/null | grep -c '^shwordsplit$' || true)"
if [ "${is_wordsplit_disabled}" != "0" ]; then setopt shwordsplit; fi
$GREP "$STRING|$NUMBER|$KEYWORD|$SPACE|." | grep -Ev "^$SPACE$"
if [ "${is_wordsplit_disabled}" != "0" ]; then unsetopt shwordsplit; fi
}
parse_array () {
local index=0
local ary=''
read -r token
case "$token" in
']') ;;
*)
while :
do
parse_value "$1" "$index"
index=$((index+1))
ary="$ary""$value"
read -r token
case "$token" in
']') break ;;
',') ary="$ary," ;;
*) throw "EXPECTED , or ] GOT ${token:-EOF}" ;;
esac
read -r token
done
;;
esac
value=$(printf '[%s]' "$ary") || value=
:
}
parse_object () {
local key
local obj=''
read -r token
case "$token" in
'}') ;;
*)
while :
do
case "$token" in
'"'*'"') key=$token ;;
*) throw "EXPECTED string GOT ${token:-EOF}" ;;
esac
read -r token
case "$token" in
':') ;;
*) throw "EXPECTED : GOT ${token:-EOF}" ;;
esac
read -r token
parse_value "$1" "$key"
obj="$obj$key:$value"
read -r token
case "$token" in
'}') break ;;
',') obj="$obj," ;;
*) throw "EXPECTED , or } GOT ${token:-EOF}" ;;
esac
read -r token
done
;;
esac
value=$(printf '{%s}' "$obj") || value=
:
}
parse_value () {
local jpath="${1:+$1,}${2:-}"
case "$token" in
'{') parse_object "$jpath" ;;
'[') parse_array "$jpath" ;;
# At this point, the only valid single-character tokens are digits.
''|[!0-9]) throw "EXPECTED value GOT ${token:-EOF}" ;;
*) value="${token//\\\///}"
# replace solidus ("\/") in json strings with normalized value: "/"
;;
esac
[ "$value" = '' ] && return
[ -z "$jpath" ] && return # do not print head
printf "[%s]\t%s\n" "$jpath" "$value"
:
}
parse () {
read -r token
parse_value
read -r token || true
case "$token" in
'') ;;
*) throw "EXPECTED EOF GOT $token" ;;
esac
}
tokenize | parse
}
# Convert IP addresses to their reverse dns variants.
# Used for ALPN certs as validation for IPs uses this in SNI since IPs aren't allowed there.
ip_to_ptr() {
ip="$(cat)"
if [[ "${ip}" =~ : ]]; then
printf "%sip6.arpa" "$(printf "%s" "${ip}" | awk -F: 'BEGIN {OFS=""; }{addCount = 9 - NF; for(i=1; i<=NF;i++){if(length($i) == 0){ for(j=1;j<=addCount;j++){$i = ($i "0000");} } else { $i = substr(("0000" $i), length($i)+5-4);}}; print}' | rev | sed -e "s/./&./g")"
else
printf "%s.in-addr.arpa" "$(printf "%s" "${ip}" | awk -F. '{print $4"."$3"." $2"."$1}')"
fi
}
# Create (identifiable) temporary files
_mktemp() {
mktemp "${TMPDIR:-/tmp}/dehydrated-XXXXXX"
}
# Check for script dependencies
check_dependencies() {
# look for required binaries
for binary in grep mktemp diff sed awk curl cut head tail hexdump; do
bin_path="$(command -v "${binary}" 2>/dev/null)" || _exiterr "This script requires ${binary}."
[[ -x "${bin_path}" ]] || _exiterr "${binary} found in PATH but it's not executable"
done
# just execute some dummy and/or version commands to see if required tools are actually usable
"${OPENSSL}" version > /dev/null 2>&1 || _exiterr "This script requires an openssl binary."
_sed "" < /dev/null > /dev/null 2>&1 || _exiterr "This script requires sed with support for extended (modern) regular expressions."
# curl returns with an error code in some ancient versions so we have to catch that
set +e
CURL_VERSION="$(curl -V 2>&1 | head -n1 | awk '{print $2}')"
set -e
}
store_configvars() {
__KEY_ALGO="${KEY_ALGO}"
__OCSP_MUST_STAPLE="${OCSP_MUST_STAPLE}"
__OCSP_FETCH="${OCSP_FETCH}"
__OCSP_DAYS="${OCSP_DAYS}"
__PRIVATE_KEY_RENEW="${PRIVATE_KEY_RENEW}"
__PRIVATE_KEY_ROLLOVER="${PRIVATE_KEY_ROLLOVER}"
__KEYSIZE="${KEYSIZE}"
__CHALLENGETYPE="${CHALLENGETYPE}"
__HOOK="${HOOK}"
__PREFERRED_CHAIN="${PREFERRED_CHAIN}"
__WELLKNOWN="${WELLKNOWN}"
__HOOK_CHAIN="${HOOK_CHAIN}"
__OPENSSL_CNF="${OPENSSL_CNF}"
__RENEW_DAYS="${RENEW_DAYS}"
__IP_VERSION="${IP_VERSION}"
__ACME_PROFILE="${ACME_PROFILE}"
__ORDER_TIMEOUT=${ORDER_TIMEOUT}
__VALIDATION_TIMEOUT=${VALIDATION_TIMEOUT}
__KEEP_GOING=${KEEP_GOING}
}
reset_configvars() {
KEY_ALGO="${__KEY_ALGO}"
OCSP_MUST_STAPLE="${__OCSP_MUST_STAPLE}"
OCSP_FETCH="${__OCSP_FETCH}"
OCSP_DAYS="${__OCSP_DAYS}"
PRIVATE_KEY_RENEW="${__PRIVATE_KEY_RENEW}"
PRIVATE_KEY_ROLLOVER="${__PRIVATE_KEY_ROLLOVER}"
KEYSIZE="${__KEYSIZE}"
CHALLENGETYPE="${__CHALLENGETYPE}"
HOOK="${__HOOK}"
PREFERRED_CHAIN="${__PREFERRED_CHAIN}"
WELLKNOWN="${__WELLKNOWN}"
HOOK_CHAIN="${__HOOK_CHAIN}"
OPENSSL_CNF="${__OPENSSL_CNF}"
RENEW_DAYS="${__RENEW_DAYS}"
IP_VERSION="${__IP_VERSION}"
ACME_PROFILE="${__ACME_PROFILE}"
ORDER_TIMEOUT=${__ORDER_TIMEOUT}
VALIDATION_TIMEOUT=${__VALIDATION_TIMEOUT}
KEEP_GOING="${__KEEP_GOING}"
}
hookscript_bricker_hook() {
# Hook scripts should ignore any hooks they don't know.
# Calling a random hook to make this clear to the hook script authors...
if [[ -n "${HOOK}" ]]; then
"${HOOK}" "this_hookscript_is_broken__dehydrated_is_working_fine__please_ignore_unknown_hooks_in_your_script" || _exiterr "Please check your hook script, it should exit cleanly without doing anything on unknown/new hooks."
fi
}
# verify configuration values
verify_config() {
[[ "${CHALLENGETYPE}" == "http-01" || "${CHALLENGETYPE}" == "dns-01" || "${CHALLENGETYPE}" == "tls-alpn-01" ]] || _exiterr "Unknown challenge type ${CHALLENGETYPE}... cannot continue."
if [[ "${COMMAND:-}" =~ sign_domains|sign_csr ]]; then
if [[ "${CHALLENGETYPE}" = "dns-01" ]] && [[ -z "${HOOK}" ]]; then
_exiterr "Challenge type dns-01 needs a hook script for deployment... cannot continue."
fi
if [[ "${CHALLENGETYPE}" = "http-01" ]] && [[ ! -d "${WELLKNOWN}" ]]; then
_exiterr "WELLKNOWN directory doesn't exist, please create ${WELLKNOWN} and set appropriate permissions."
fi
fi
[[ "${KEY_ALGO}" == "rsa" || "${KEY_ALGO}" == "prime256v1" || "${KEY_ALGO}" == "secp384r1" || "${KEY_ALGO}" == "secp521r1" ]] || _exiterr "Unknown public key algorithm ${KEY_ALGO}... cannot continue."
if [[ -n "${IP_VERSION}" ]]; then
[[ "${IP_VERSION}" = "4" || "${IP_VERSION}" = "6" ]] || _exiterr "Unknown IP version ${IP_VERSION}... cannot continue."
fi
[[ "${API}" == "auto" || "${API}" == "1" || "${API}" == "2" ]] || _exiterr "Unsupported API version defined in config: ${API}"
[[ "${OCSP_DAYS}" =~ ^[0-9]+$ ]] || _exiterr "OCSP_DAYS must be a number"
[[ "${ORDER_TIMEOUT}" =~ ^[0-9]+$ ]] || _exiterr "ORDER_TIMEOUT must be a number"
[[ "${VALIDATION_TIMEOUT}" =~ ^[0-9]+$ ]] || _exiterr "VALIDATION_TIMEOUT must be a number"
}
# Setup default config values, search for and load configuration files
load_config() {
# Check for config in various locations
if [[ -z "${CONFIG:-}" ]]; then
for check_config in "/etc/dehydrated" "/usr/local/etc/dehydrated" "${PWD}" "${SCRIPTDIR}"; do
if [[ -f "${check_config}/config" ]]; then
BASEDIR="${check_config}"
CONFIG="${check_config}/config"
break
fi
done
fi
# Preset
CA_ZEROSSL="https://acme.zerossl.com/v2/DV90"
CA_LETSENCRYPT="https://acme-v02.api.letsencrypt.org/directory"
CA_LETSENCRYPT_TEST="https://acme-staging-v02.api.letsencrypt.org/directory"
CA_BUYPASS="https://api.buypass.com/acme/directory"
CA_BUYPASS_TEST="https://api.test4.buypass.no/acme/directory"
CA_GOOGLE="https://dv.acme-v02.api.pki.goog/directory"
CA_GOOGLE_TEST="https://dv.acme-v02.test-api.pki.goog/directory"
# Default values
CA="letsencrypt"
OLDCA=
CERTDIR=
ALPNCERTDIR=
ACCOUNTDIR=
ACCOUNT_KEYSIZE="4096"
ACCOUNT_KEY_ALGO=rsa
CHALLENGETYPE="http-01"
CONFIG_D=
CURL_OPTS=
DOMAINS_D=
DOMAINS_TXT=
HOOK=
PREFERRED_CHAIN=
HOOK_CHAIN="no"
RENEW_DAYS="32"
KEYSIZE="4096"
WELLKNOWN=
PRIVATE_KEY_RENEW="yes"
PRIVATE_KEY_ROLLOVER="no"
KEY_ALGO=secp384r1
OPENSSL=openssl
OPENSSL_CNF=
CONTACT_EMAIL=
LOCKFILE=
OCSP_MUST_STAPLE="no"
OCSP_FETCH="no"
OCSP_DAYS=5
IP_VERSION=
CHAINCACHE=
AUTO_CLEANUP="no"
AUTO_CLEANUP_DELETE="no"
DEHYDRATED_USER=
DEHYDRATED_GROUP=
API="auto"
ACME_PROFILE=""
ORDER_TIMEOUT=0
VALIDATION_TIMEOUT=0
KEEP_GOING="no"
if [[ -z "${CONFIG:-}" ]]; then
echo "#" >&2
echo "# !! WARNING !! No main config file found, using default config!" >&2
echo "#" >&2
elif [[ -f "${CONFIG}" ]]; then
echo "# INFO: Using main config file ${CONFIG}"
BASEDIR="$(dirname "${CONFIG}")"
# shellcheck disable=SC1090
. "${CONFIG}"
else
_exiterr "Specified config file doesn't exist."
fi
if [[ -n "${CONFIG_D}" ]]; then
if [[ ! -d "${CONFIG_D}" ]]; then
_exiterr "The path ${CONFIG_D} specified for CONFIG_D does not point to a directory."
fi
# Allow globbing
noglob_set
for check_config_d in "${CONFIG_D}"/*.sh; do
if [[ -f "${check_config_d}" ]] && [[ -r "${check_config_d}" ]]; then
echo "# INFO: Using additional config file ${check_config_d}"
# shellcheck disable=SC1090
. "${check_config_d}"
else
_exiterr "Specified additional config ${check_config_d} is not readable or not a file at all."
fi
done
# Disable globbing
noglob_clear
fi
# Check for missing dependencies
check_dependencies
has_sudo() {
command -v sudo > /dev/null 2>&1 || _exiterr "DEHYDRATED_USER set but sudo not available. Please install sudo."
}
# Check if we are running & are allowed to run as root
if [[ -n "$DEHYDRATED_USER" ]]; then
command -v getent > /dev/null 2>&1 || _exiterr "DEHYDRATED_USER set but getent not available. Please install getent."
TARGET_UID="$(getent passwd "${DEHYDRATED_USER}" | cut -d':' -f3)" || _exiterr "DEHYDRATED_USER ${DEHYDRATED_USER} is invalid"
if [[ -z "${DEHYDRATED_GROUP}" ]]; then
if [[ "${EUID}" != "${TARGET_UID}" ]]; then
echo "# INFO: Running $0 as ${DEHYDRATED_USER}"
has_sudo && exec sudo -u "${DEHYDRATED_USER}" "${0}" "${ORIGARGS[@]}"
fi
else
TARGET_GID="$(getent group "${DEHYDRATED_GROUP}" | cut -d':' -f3)" || _exiterr "DEHYDRATED_GROUP ${DEHYDRATED_GROUP} is invalid"
if [[ -z "${EGID:-}" ]]; then
command -v id > /dev/null 2>&1 || _exiterr "DEHYDRATED_GROUP set, don't know current gid and 'id' not available... Please provide 'id' binary."
EGID="$(id -g)"
fi
if [[ "${EUID}" != "${TARGET_UID}" ]] || [[ "${EGID}" != "${TARGET_GID}" ]]; then
echo "# INFO: Running $0 as ${DEHYDRATED_USER}/${DEHYDRATED_GROUP}"
has_sudo && exec sudo -u "${DEHYDRATED_USER}" -g "${DEHYDRATED_GROUP}" "${0}" "${ORIGARGS[@]}"
fi
fi
elif [[ -n "${DEHYDRATED_GROUP}" ]]; then
_exiterr "DEHYDRATED_GROUP can only be used in combination with DEHYDRATED_USER."
fi
# Remove slash from end of BASEDIR. Mostly for cleaner outputs, doesn't change functionality.
[[ "$BASEDIR" != "/" ]] && BASEDIR="${BASEDIR%%/}"
# Check BASEDIR and set default variables
[[ -d "${BASEDIR}" ]] || _exiterr "BASEDIR does not exist: ${BASEDIR}"
# Check for ca cli parameter
if [ -n "${PARAM_CA:-}" ]; then
CA="${PARAM_CA}"
fi
# Preset CAs
if [ "${CA}" = "letsencrypt" ]; then
CA="${CA_LETSENCRYPT}"
elif [ "${CA}" = "letsencrypt-test" ]; then
CA="${CA_LETSENCRYPT_TEST}"
elif [ "${CA}" = "zerossl" ]; then
CA="${CA_ZEROSSL}"
elif [ "${CA}" = "buypass" ]; then
CA="${CA_BUYPASS}"
elif [ "${CA}" = "buypass-test" ]; then
CA="${CA_BUYPASS_TEST}"
elif [ "${CA}" = "google" ]; then
CA="${CA_GOOGLE}"
elif [ "${CA}" = "google-test" ]; then
CA="${CA_GOOGLE_TEST}"
fi
if [[ -z "${OLDCA}" ]] && [[ "${CA}" = "https://acme-v02.api.letsencrypt.org/directory" ]]; then
OLDCA="https://acme-v01.api.letsencrypt.org/directory"
fi
# Create new account directory or symlink to account directory from old CA
# dev note: keep in mind that because of the use of 'echo' instead of 'printf' or
# similar there is a newline encoded in the directory name. not going to fix this
# since it's a non-issue and trying to fix existing installations would be too much
# trouble
CAHASH="$(echo "${CA}" | urlbase64)"
[[ -z "${ACCOUNTDIR}" ]] && ACCOUNTDIR="${BASEDIR}/accounts"
if [[ ! -e "${ACCOUNTDIR}/${CAHASH}" ]]; then
OLDCAHASH="$(echo "${OLDCA}" | urlbase64)"
mkdir -p "${ACCOUNTDIR}"
if [[ -n "${OLDCA}" ]] && [[ -e "${ACCOUNTDIR}/${OLDCAHASH}" ]]; then
echo "! Reusing account from ${OLDCA}"
ln -s "${OLDCAHASH}" "${ACCOUNTDIR}/${CAHASH}"
else
mkdir "${ACCOUNTDIR}/${CAHASH}"
fi
fi
# shellcheck disable=SC1090
[[ -f "${ACCOUNTDIR}/${CAHASH}/config" ]] && . "${ACCOUNTDIR}/${CAHASH}/config"
ACCOUNT_KEY="${ACCOUNTDIR}/${CAHASH}/account_key.pem"
ACCOUNT_KEY_JSON="${ACCOUNTDIR}/${CAHASH}/registration_info.json"
ACCOUNT_ID_JSON="${ACCOUNTDIR}/${CAHASH}/account_id.json"
ACCOUNT_DEACTIVATED="${ACCOUNTDIR}/${CAHASH}/deactivated"
if [[ -f "${ACCOUNT_DEACTIVATED}" ]]; then
_exiterr "Account has been deactivated. Remove account and create a new one using --register."
fi
if [[ -f "${BASEDIR}/private_key.pem" ]] && [[ ! -f "${ACCOUNT_KEY}" ]]; then
echo "! Moving private_key.pem to ${ACCOUNT_KEY}"
mv "${BASEDIR}/private_key.pem" "${ACCOUNT_KEY}"
fi
if [[ -f "${BASEDIR}/private_key.json" ]] && [[ ! -f "${ACCOUNT_KEY_JSON}" ]]; then
echo "! Moving private_key.json to ${ACCOUNT_KEY_JSON}"
mv "${BASEDIR}/private_key.json" "${ACCOUNT_KEY_JSON}"
fi
[[ -z "${CERTDIR}" ]] && CERTDIR="${BASEDIR}/certs"
[[ -z "${ALPNCERTDIR}" ]] && ALPNCERTDIR="${BASEDIR}/alpn-certs"
[[ -z "${CHAINCACHE}" ]] && CHAINCACHE="${BASEDIR}/chains"
[[ -z "${DOMAINS_TXT}" ]] && DOMAINS_TXT="${BASEDIR}/domains.txt"
[[ -z "${WELLKNOWN}" ]] && WELLKNOWN="/var/www/dehydrated"
[[ -z "${LOCKFILE}" ]] && LOCKFILE="${BASEDIR}/lock"
[[ -z "${OPENSSL_CNF}" ]] && OPENSSL_CNF="$("${OPENSSL}" version -d | cut -d\" -f2)/openssl.cnf"
[[ -n "${PARAM_LOCKFILE_SUFFIX:-}" ]] && LOCKFILE="${LOCKFILE}-${PARAM_LOCKFILE_SUFFIX}"
[[ -n "${PARAM_NO_LOCK:-}" ]] && LOCKFILE=""
[[ -n "${PARAM_HOOK:-}" ]] && HOOK="${PARAM_HOOK}"
[[ -n "${PARAM_DOMAINS_TXT:-}" ]] && DOMAINS_TXT="${PARAM_DOMAINS_TXT}"
[[ -n "${PARAM_PREFERRED_CHAIN:-}" ]] && PREFERRED_CHAIN="${PARAM_PREFERRED_CHAIN}"
[[ -n "${PARAM_CERTDIR:-}" ]] && CERTDIR="${PARAM_CERTDIR}"
[[ -n "${PARAM_ALPNCERTDIR:-}" ]] && ALPNCERTDIR="${PARAM_ALPNCERTDIR}"
[[ -n "${PARAM_CHALLENGETYPE:-}" ]] && CHALLENGETYPE="${PARAM_CHALLENGETYPE}"
[[ -n "${PARAM_KEY_ALGO:-}" ]] && KEY_ALGO="${PARAM_KEY_ALGO}"
[[ -n "${PARAM_OCSP_MUST_STAPLE:-}" ]] && OCSP_MUST_STAPLE="${PARAM_OCSP_MUST_STAPLE}"
[[ -n "${PARAM_IP_VERSION:-}" ]] && IP_VERSION="${PARAM_IP_VERSION}"
[[ -n "${PARAM_ACME_PROFILE:-}" ]] && ACME_PROFILE="${PARAM_ACME_PROFILE}"
[[ -n "${PARAM_ORDER_TIMEOUT:-}" ]] && ORDER_TIMEOUT="${PARAM_ORDER_TIMEOUT}"
[[ -n "${PARAM_VALIDATION_TIMEOUT:-}" ]] && VALIDATION_TIMEOUT="${PARAM_VALIDATION_TIMEOUT}"
[[ -n "${PARAM_KEEP_GOING:-}" ]] && KEEP_GOING="${PARAM_KEEP_GOING}"
if [ "${PARAM_FORCE_VALIDATION:-no}" = "yes" ] && [ "${PARAM_FORCE:-no}" = "no" ]; then
_exiterr "Argument --force-validation can only be used in combination with --force (-x)"
fi
if [ ! "${1:-}" = "noverify" ]; then
verify_config
fi
store_configvars
}
# Initialize system
init_system() {
load_config
# Lockfile handling (prevents concurrent access)
if [[ -n "${LOCKFILE}" ]]; then
LOCKDIR="$(dirname "${LOCKFILE}")"
[[ -w "${LOCKDIR}" ]] || _exiterr "Directory ${LOCKDIR} for LOCKFILE ${LOCKFILE} is not writable, aborting."
( set -C; date > "${LOCKFILE}" ) 2>/dev/null || _exiterr "Lock file '${LOCKFILE}' present, aborting."
remove_lock() { rm -f "${LOCKFILE}"; }
trap 'remove_lock' EXIT
fi
# Get CA URLs
CA_DIRECTORY="$(http_request get "${CA}" | jsonsh)"
# Automatic discovery of API version
if [[ "${API}" = "auto" ]]; then
grep -q newOrder <<< "${CA_DIRECTORY}" && API=2 || API=1
fi
# shellcheck disable=SC2015
if [[ "${API}" = "1" ]]; then
CA_NEW_CERT="$(printf "%s" "${CA_DIRECTORY}" | get_json_string_value new-cert)" &&
CA_NEW_AUTHZ="$(printf "%s" "${CA_DIRECTORY}" | get_json_string_value new-authz)" &&
CA_NEW_REG="$(printf "%s" "${CA_DIRECTORY}" | get_json_string_value new-reg)" &&
CA_TERMS="$(printf "%s" "${CA_DIRECTORY}" | get_json_string_value terms-of-service)" &&
CA_REQUIRES_EAB="false" &&
CA_REVOKE_CERT="$(printf "%s" "${CA_DIRECTORY}" | get_json_string_value revoke-cert)" ||
_exiterr "Problem retrieving ACME/CA-URLs, check if your configured CA points to the directory entrypoint."
# Since reg URI is missing from directory we will assume it is the same as CA_NEW_REG without the new part
CA_REG=${CA_NEW_REG/new-reg/reg}
if [[ -n "${ACME_PROFILE}" ]]; then
_exiterr "ACME profiles are not supported in ACME v1."
fi
else
CA_NEW_ORDER="$(printf "%s" "${CA_DIRECTORY}" | get_json_string_value newOrder)" &&
CA_NEW_NONCE="$(printf "%s" "${CA_DIRECTORY}" | get_json_string_value newNonce)" &&
CA_NEW_ACCOUNT="$(printf "%s" "${CA_DIRECTORY}" | get_json_string_value newAccount)" &&
CA_TERMS="$(printf "%s" "${CA_DIRECTORY}" | get_json_string_value -p '"meta","termsOfService"')" &&
CA_REQUIRES_EAB="$(printf "%s" "${CA_DIRECTORY}" | get_json_bool_value -p '"meta","externalAccountRequired"' || echo false)" &&
CA_REVOKE_CERT="$(printf "%s" "${CA_DIRECTORY}" | get_json_string_value revokeCert)" ||
_exiterr "Problem retrieving ACME/CA-URLs, check if your configured CA points to the directory entrypoint."
# Checking ACME profile
if [[ -n "${ACME_PROFILE}" ]]; then
# Extract available profiles from CA directory
declare -A available_profiles=()
while IFS=$'\t' read -r path value; do
if [[ "${value}" =~ ^\"([^\"]+)\"$ ]]; then
value=${BASH_REMATCH[1]}
fi
if [[ "${path}" =~ ^\[\"([^\"]+)\"\]$ ]]; then
available_profiles[${BASH_REMATCH[1]}]=$value
fi
done <<< "$(printf "%s" "${CA_DIRECTORY}" | get_json_dict_value -p '"meta","profiles"' 2>/dev/null)"
if [[ ${#available_profiles[@]} -eq 0 ]]; then
_exiterr "ACME profile not supported by this CA"
fi
# Check if the requested profile is available
found_profile="no"
for profile in "${!available_profiles[@]}"; do
if [[ "${profile}" == "${ACME_PROFILE}" ]]; then
found_profile="yes"
break
fi
done
if [[ "${found_profile}" == "no" ]]; then
_exiterr "ACME profile '${ACME_PROFILE}' not found, available profiles:$(for key in "${!available_profiles[@]}"; do printf "\n %s: %s" "${key}" "${available_profiles[$key]}"; done)"
fi
fi
fi
# Export some environment variables to be used in hook script
export WELLKNOWN BASEDIR CERTDIR ALPNCERTDIR CONFIG COMMAND
# Checking for private key ...
register_new_key="no"
generated="false"
if [[ -n "${PARAM_ACCOUNT_KEY:-}" ]]; then
# a private key was specified from the command line so use it for this run
echo "Using private key ${PARAM_ACCOUNT_KEY} instead of account key"
ACCOUNT_KEY="${PARAM_ACCOUNT_KEY}"
ACCOUNT_KEY_JSON="${PARAM_ACCOUNT_KEY}.json"
ACCOUNT_ID_JSON="${PARAM_ACCOUNT_KEY}_id.json"
[ "${COMMAND:-}" = "register" ] && register_new_key="yes"
else
# Check if private account key exists, if it doesn't exist yet generate a new one (rsa key)
if [[ ! -e "${ACCOUNT_KEY}" ]]; then
if [[ ! "${PARAM_ACCEPT_TERMS:-}" = "yes" ]]; then
printf '\n' >&2
printf 'To use dehydrated with this certificate authority you have to agree to their terms of service which you can find here: %s\n\n' "${CA_TERMS}" >&2
printf 'To accept these terms of service run "%s --register --accept-terms".\n' "${0}" >&2
exit 1
fi
echo "+ Generating account key..."
generated="true"
local tmp_account_key
tmp_account_key="$(_mktemp)"
if [[ ${API} -eq 1 && ! "${ACCOUNT_KEY_ALGO}" = "rsa" ]]; then
_exiterr "ACME API version 1 does not support EC account keys"
fi
case "${ACCOUNT_KEY_ALGO}" in
rsa) _openssl genrsa -out "${tmp_account_key}" "${ACCOUNT_KEYSIZE}";;
prime256v1|secp384r1|secp521r1) _openssl ecparam -genkey -name "${ACCOUNT_KEY_ALGO}" -out "${tmp_account_key}" -noout;;
esac
cat "${tmp_account_key}" > "${ACCOUNT_KEY}"
rm "${tmp_account_key}"
register_new_key="yes"
fi
fi
if ("${OPENSSL}" rsa -in "${ACCOUNT_KEY}" -check 2>/dev/null > /dev/null); then
# Get public components from private key and calculate thumbprint
pubExponent64="$(printf '%x' "$("${OPENSSL}" rsa -in "${ACCOUNT_KEY}" -noout -text | awk '/publicExponent/ {print $2}')" | hex2bin | urlbase64)"
pubMod64="$("${OPENSSL}" rsa -in "${ACCOUNT_KEY}" -noout -modulus | cut -d'=' -f2 | hex2bin | urlbase64)"
account_key_info="$(printf '{"e":"%s","kty":"RSA","n":"%s"}' "${pubExponent64}" "${pubMod64}")"
account_key_sigalgo=RS256
elif ("${OPENSSL}" ec -in "${ACCOUNT_KEY}" -check 2>/dev/null > /dev/null); then
curve="$("${OPENSSL}" ec -in "${ACCOUNT_KEY}" -noout -text 2>/dev/null | grep 'NIST CURVE' | cut -d':' -f2 | tr -d ' ')"
pubkey="$("${OPENSSL}" ec -in "${ACCOUNT_KEY}" -noout -text 2>/dev/null | tr -d '\n ' | grep -Eo 'pub:.*ASN1' | _sed -e 's/^pub://' -e 's/ASN1$//' | tr -d ':')"
if [ "${curve}" = "P-256" ]; then
account_key_sigalgo="ES256"
elif [ "${curve}" = "P-384" ]; then
account_key_sigalgo="ES384"
elif [ "${curve}" = "P-521" ]; then
account_key_sigalgo="ES512"
else
_exiterr "Unknown account key curve: ${curve}"
fi
ec_x_offset=2
ec_x_len=$((${#pubkey}/2 - 1))
ec_x="${pubkey:$ec_x_offset:$ec_x_len}"
ec_x64="$(printf "%s" "${ec_x}" | hex2bin | urlbase64)"
ec_y_offset=$((ec_x_offset+ec_x_len))
ec_y_len=$((${#pubkey}-ec_y_offset))
ec_y="${pubkey:$ec_y_offset:$ec_y_len}"
ec_y64="$(printf "%s" "${ec_y}" | hex2bin | urlbase64)"
account_key_info="$(printf '{"crv":"%s","kty":"EC","x":"%s","y":"%s"}' "${curve}" "${ec_x64}" "${ec_y64}")"
else
_exiterr "Account key is not valid, cannot continue."
fi
thumbprint="$(printf '%s' "${account_key_info}" | "${OPENSSL}" dgst -sha256 -binary | urlbase64)"
# If we generated a new private key in the step above we have to register it with the acme-server
if [[ "${register_new_key}" = "yes" ]]; then
echo "+ Registering account key with ACME server..."
FAILED=false
if [[ ${API} -eq 1 && -z "${CA_NEW_REG}" ]] || [[ ${API} -eq 2 && -z "${CA_NEW_ACCOUNT}" ]]; then
echo "Certificate authority doesn't allow registrations."
FAILED=true
fi
# ZeroSSL special sauce
if [[ "${CA}" = "${CA_ZEROSSL}" ]]; then
if [[ -z "${EAB_KID:-}" ]] || [[ -z "${EAB_HMAC_KEY:-}" ]]; then
if [[ -z "${CONTACT_EMAIL}" ]]; then
echo "ZeroSSL requires contact email to be set or EAB_KID/EAB_HMAC_KEY to be manually configured"
FAILED=true
else
zeroapi="$(curl -s "https://api.zerossl.com/acme/eab-credentials-email" -d "email=${CONTACT_EMAIL}" | jsonsh)"
EAB_KID="$(printf "%s" "${zeroapi}" | get_json_string_value eab_kid)"
EAB_HMAC_KEY="$(printf "%s" "${zeroapi}" | get_json_string_value eab_hmac_key)"
if [[ -z "${EAB_KID:-}" ]] || [[ -z "${EAB_HMAC_KEY:-}" ]]; then
echo "Unknown error retrieving ZeroSSL API credentials"
echo "${zeroapi}"
FAILED=true
fi
fi
fi
fi
# Google special sauce
if [[ "${CA}" = "${CA_GOOGLE}" ]]; then
if [[ -z "${CONTACT_EMAIL}" ]] || [[ -z "${EAB_KID:-}" ]] || [[ -z "${EAB_HMAC_KEY:-}" ]]; then
echo "Google requires contact email, EAB_KID and EAB_HMAC_KEY to be manually configured (see https://cloud.google.com/certificate-manager/docs/public-ca-tutorial)"
FAILED=true
fi
fi
# Check if external account is required
if [[ "${FAILED}" = "false" ]]; then
if [[ "${CA_REQUIRES_EAB}" = "true" ]]; then
if [[ -z "${EAB_KID:-}" ]] || [[ -z "${EAB_HMAC_KEY:-}" ]]; then
FAILED=true
echo "This CA requires an external account but no EAB_KID/EAB_HMAC_KEY has been configured"
fi
fi
fi
# If an email for the contact has been provided then adding it to the registration request
if [[ "${FAILED}" = "false" ]]; then
if [[ ${API} -eq 1 ]]; then
if [[ -n "${CONTACT_EMAIL}" ]]; then
(signed_request "${CA_NEW_REG}" '{"resource": "new-reg", "contact":["mailto:'"${CONTACT_EMAIL}"'"], "agreement": "'"${CA_TERMS}"'"}' > "${ACCOUNT_KEY_JSON}") || FAILED=true
else
(signed_request "${CA_NEW_REG}" '{"resource": "new-reg", "agreement": "'"${CA_TERMS}"'"}' > "${ACCOUNT_KEY_JSON}") || FAILED=true
fi
else
if [[ -n "${EAB_KID:-}" ]] && [[ -n "${EAB_HMAC_KEY:-}" ]]; then
eab_url="${CA_NEW_ACCOUNT}"
eab_protected64="$(printf '{"alg":"HS256","kid":"%s","url":"%s"}' "${EAB_KID}" "${eab_url}" | urlbase64)"
eab_payload64="$(printf "%s" "${account_key_info}" | urlbase64)"
eab_key="$(printf "%s" "${EAB_HMAC_KEY}" | deurlbase64 | bin2hex)"
eab_signed64="$(printf '%s' "${eab_protected64}.${eab_payload64}" | "${OPENSSL}" dgst -binary -sha256 -mac HMAC -macopt "hexkey:${eab_key}" | urlbase64)"
if [[ -n "${CONTACT_EMAIL}" ]]; then
regjson='{"contact":["mailto:'"${CONTACT_EMAIL}"'"], "termsOfServiceAgreed": true, "externalAccountBinding": {"protected": "'"${eab_protected64}"'", "payload": "'"${eab_payload64}"'", "signature": "'"${eab_signed64}"'"}}'
else
regjson='{"termsOfServiceAgreed": true, "externalAccountBinding": {"protected": "'"${eab_protected64}"'", "payload": "'"${eab_payload64}"'", "signature": "'"${eab_signed64}"'"}}'
fi
else
if [[ -n "${CONTACT_EMAIL}" ]]; then
regjson='{"contact":["mailto:'"${CONTACT_EMAIL}"'"], "termsOfServiceAgreed": true}'
else
regjson='{"termsOfServiceAgreed": true}'
fi
fi
(signed_request "${CA_NEW_ACCOUNT}" "${regjson}" > "${ACCOUNT_KEY_JSON}") || FAILED=true
fi
fi
if [[ "${FAILED}" = "true" ]]; then
echo >&2
echo >&2
echo "Error registering account key. See message above for more information." >&2
if [[ "${generated}" = "true" ]]; then
rm "${ACCOUNT_KEY}"
fi
rm -f "${ACCOUNT_KEY_JSON}"
exit 1
fi
elif [[ "${COMMAND:-}" = "register" ]]; then
echo "+ Account already registered!"
exit 0
fi
# Read account information or request from CA if missing
if [[ -e "${ACCOUNT_KEY_JSON}" ]]; then
if [[ ${API} -eq 1 ]]; then
ACCOUNT_ID="$(jsonsh < "${ACCOUNT_KEY_JSON}" | get_json_int_value id)"
ACCOUNT_URL="${CA_REG}/${ACCOUNT_ID}"
else
if [[ -e "${ACCOUNT_ID_JSON}" ]]; then
ACCOUNT_URL="$(jsonsh < "${ACCOUNT_ID_JSON}" | get_json_string_value url)"
fi
# if account URL is not storred, fetch it from the CA
if [[ -z "${ACCOUNT_URL:-}" ]]; then
echo "+ Fetching account URL..."
ACCOUNT_URL="$(signed_request "${CA_NEW_ACCOUNT}" '{"onlyReturnExisting": true}' 4>&1 | grep -i ^Location: | cut -d':' -f2- | tr -d ' \t\r\n')"
if [[ -z "${ACCOUNT_URL}" ]]; then
_exiterr "Unknown error on fetching account information"
fi
echo '{"url":"'"${ACCOUNT_URL}"'"}' > "${ACCOUNT_ID_JSON}" # store the URL for next time
fi
fi
else
echo "Fetching missing account information from CA..."
if [[ ${API} -eq 1 ]]; then
_exiterr "This is not implemented for ACMEv1! Consider switching to ACMEv2 :)"
else
ACCOUNT_URL="$(signed_request "${CA_NEW_ACCOUNT}" '{"onlyReturnExisting": true}' 4>&1 | grep -i ^Location: | cut -d':' -f2- | tr -d ' \t\r\n')"
ACCOUNT_INFO="$(signed_request "${ACCOUNT_URL}" '{}')"
fi
echo "${ACCOUNT_INFO}" > "${ACCOUNT_KEY_JSON}"
fi
}
# Different sed version for different os types...
_sed() {
if [[ "${OSTYPE}" = "Linux" || "${OSTYPE:0:5}" = "MINGW" ]]; then
sed -r "${@}"
else
sed -E "${@}"
fi
}
# Print error message and exit with error
_exiterr() {
if [ -n "${1:-}" ]; then
echo "ERROR: ${1}" >&2
fi
[[ "${skip_exit_hook:-no}" = "no" ]] && [[ -n "${HOOK:-}" ]] && ("${HOOK}" "exit_hook" "${1:-}" || echo 'exit_hook returned with non-zero exit code!' >&2)
exit 1
}
# Remove newlines and whitespace from json
clean_json() {
tr -d '\r\n' | _sed -e 's/ +/ /g' -e 's/\{ /{/g' -e 's/ \}/}/g' -e 's/\[ /[/g' -e 's/ \]/]/g'
}
# Encode data as url-safe formatted base64
urlbase64() {
# urlbase64: base64 encoded string with '+' replaced with '-' and '/' replaced with '_'
"${OPENSSL}" base64 -e | tr -d '\n\r' | _sed -e 's:=*$::g' -e 'y:+/:-_:'
}
# Decode data from url-safe formatted base64
deurlbase64() {
data="$(cat | tr -d ' \n\r')"
modlen=$((${#data} % 4))
padding=""
if [[ "${modlen}" = "2" ]]; then padding="==";
elif [[ "${modlen}" = "3" ]]; then padding="="; fi
printf "%s%s" "${data}" "${padding}" | tr -d '\n\r' | _sed -e 'y:-_:+/:' | "${OPENSSL}" base64 -d -A
}
# Convert hex string to binary data
hex2bin() {
# Remove spaces, add leading zero, escape as hex string and parse with printf
# shellcheck disable=SC2059
printf "%b" "$(cat | _sed -e 's/[[:space:]]//g' -e 's/^(.(.{2})*)$/0\1/' -e 's/(.{2})/\\x\1/g')"
}
# Convert binary data to hex string
bin2hex() {
hexdump -v -e '/1 "%02x"'
}
# OpenSSL writes to stderr/stdout even when there are no errors. So just
# display the output if the exit code was != 0 to simplify debugging.
_openssl() {
set +e
out="$("${OPENSSL}" "${@}" 2>&1)"
res=$?
set -e
if [[ ${res} -ne 0 ]]; then
echo " + ERROR: failed to run $* (Exitcode: ${res})" >&2
echo >&2
echo "Details:" >&2
echo "${out}" >&2
echo >&2
exit "${res}"
fi
}
# Send http(s) request with specified method
http_request() {
tempcont="$(_mktemp)"
tempheaders="$(_mktemp)"
if [[ -n "${IP_VERSION:-}" ]]; then
ip_version="-${IP_VERSION}"
fi
set +e
# shellcheck disable=SC2086
if [[ "${1}" = "head" ]]; then
statuscode="$(curl ${ip_version:-} ${CURL_OPTS} -A "dehydrated/${VERSION} curl/${CURL_VERSION}" -s -w "%{http_code}" -o "${tempcont}" -H 'Cache-Control: no-cache' "${2}" -I)"
curlret="${?}"
touch "${tempheaders}"
elif [[ "${1}" = "get" ]]; then
statuscode="$(curl ${ip_version:-} ${CURL_OPTS} -A "dehydrated/${VERSION} curl/${CURL_VERSION}" -L -s -w "%{http_code}" -o "${tempcont}" -D "${tempheaders}" -H 'Cache-Control: no-cache' "${2}")"
curlret="${?}"
elif [[ "${1}" = "post" ]]; then
statuscode="$(curl ${ip_version:-} ${CURL_OPTS} -A "dehydrated/${VERSION} curl/${CURL_VERSION}" -s -w "%{http_code}" -o "${tempcont}" "${2}" -D "${tempheaders}" -H 'Cache-Control: no-cache' -H 'Content-Type: application/jose+json' -d "${3}")"
curlret="${?}"
else
set -e
_exiterr "Unknown request method: ${1}"
fi
set -e
if [[ ! "${curlret}" = "0" ]]; then
_exiterr "Problem connecting to server (${1} for ${2}; curl returned with ${curlret})"
fi
if [[ ! "${statuscode:0:1}" = "2" ]]; then
# check for existing registration warning
if [[ "${API}" = "1" ]] && [[ -n "${CA_NEW_REG:-}" ]] && [[ "${2}" = "${CA_NEW_REG:-}" ]] && [[ "${statuscode}" = "409" ]] && grep -q "Registration key is already in use" "${tempcont}"; then
# do nothing
:
# check for already-revoked warning
elif [[ -n "${CA_REVOKE_CERT:-}" ]] && [[ "${2}" = "${CA_REVOKE_CERT:-}" ]] && [[ "${statuscode}" = "409" ]]; then
grep -q "Certificate already revoked" "${tempcont}" && return
else
if grep -q "urn:ietf:params:acme:error:badNonce" "${tempcont}"; then
printf "badnonce %s" "$(grep -Eoi "^replay-nonce:.*$" "${tempheaders}" | sed 's/ //' | cut -d: -f2)"
return 0
fi
echo " + ERROR: An error occurred while sending ${1}-request to ${2} (Status ${statuscode})" >&2
echo >&2
echo "Details:" >&2
cat "${tempheaders}" >&2
cat "${tempcont}" >&2
echo >&2
echo >&2
# An exclusive hook for the {1}-request error might be useful (e.g., for sending an e-mail to admins)
if [[ -n "${HOOK}" ]]; then
errtxt="$(cat "${tempcont}")"
errheaders="$(cat "${tempheaders}")"
"${HOOK}" "request_failure" "${statuscode}" "${errtxt}" "${1}" "${errheaders}" || _exiterr 'request_failure hook returned with non-zero exit code'
fi
rm -f "${tempcont}"
rm -f "${tempheaders}"
# remove temporary domains.txt file if used
[[ "${COMMAND:-}" = "sign_domains" && -n "${PARAM_DOMAIN:-}" && -n "${DOMAINS_TXT:-}" ]] && rm "${DOMAINS_TXT}"
_exiterr
fi
fi
if { true >&4; } 2>/dev/null; then
cat "${tempheaders}" >&4
fi
cat "${tempcont}"
rm -f "${tempcont}"
rm -f "${tempheaders}"
}
# Send signed request
signed_request() {
# Encode payload as urlbase64
payload64="$(printf '%s' "${2}" | urlbase64)"
if [ -n "${3:-}" ]; then
nonce="$(printf "%s" "${3}" | tr -d ' \t\n\r')"
else
# Retrieve nonce from acme-server
if [[ ${API} -eq 1 ]]; then
nonce="$(http_request head "${CA}" | grep -i ^Replay-Nonce: | cut -d':' -f2- | tr -d ' \t\n\r')"
else
nonce="$(http_request head "${CA_NEW_NONCE}" | grep -i ^Replay-Nonce: | cut -d':' -f2- | tr -d ' \t\n\r')"
fi
fi
if [[ ${API} -eq 1 ]]; then
# Build another header which also contains the previously received nonce and encode it as urlbase64
protected='{"alg": "RS256", "jwk": {"e": "'"${pubExponent64}"'", "kty": "RSA", "n": "'"${pubMod64}"'"}, "nonce": "'"${nonce}"'"}'
protected64="$(printf '%s' "${protected}" | urlbase64)"
else
# Build another header which also contains the previously received nonce and url and encode it as urlbase64
if [[ -n "${ACCOUNT_URL:-}" ]]; then
protected='{"alg": "'"${account_key_sigalgo}"'", "kid": "'"${ACCOUNT_URL}"'", "url": "'"${1}"'", "nonce": "'"${nonce}"'"}'
else
protected='{"alg": "'"${account_key_sigalgo}"'", "jwk": '"${account_key_info}"', "url": "'"${1}"'", "nonce": "'"${nonce}"'"}'
fi
protected64="$(printf '%s' "${protected}" | urlbase64)"
fi
# Sign header with nonce and our payload with our private key and encode signature as urlbase64
if [[ "${account_key_sigalgo}" = "RS256" ]]; then
signed64="$(printf '%s' "${protected64}.${payload64}" | "${OPENSSL}" dgst -sha256 -sign "${ACCOUNT_KEY}" | urlbase64)"
else
dgstparams="$(printf '%s' "${protected64}.${payload64}" | "${OPENSSL}" dgst -sha${account_key_sigalgo:2} -sign "${ACCOUNT_KEY}" | "${OPENSSL}" asn1parse -inform DER)"
dgst_parm_1="$(echo "$dgstparams" | head -n 2 | tail -n 1 | cut -d':' -f4)"
dgst_parm_2="$(echo "$dgstparams" | head -n 3 | tail -n 1 | cut -d':' -f4)"
# zero-padding (doesn't seem to be necessary, but other clients are doing this as well...
case "${account_key_sigalgo}" in
"ES256") siglen=64;;
"ES384") siglen=96;;
"ES512") siglen=132;;
esac
while [[ ${#dgst_parm_1} -lt $siglen ]]; do dgst_parm_1="0${dgst_parm_1}"; done
while [[ ${#dgst_parm_2} -lt $siglen ]]; do dgst_parm_2="0${dgst_parm_2}"; done
signed64="$(printf "%s%s" "${dgst_parm_1}" "${dgst_parm_2}" | hex2bin | urlbase64)"
fi
if [[ ${API} -eq 1 ]]; then
# Build header with just our public key and algorithm information
header='{"alg": "RS256", "jwk": {"e": "'"${pubExponent64}"'", "kty": "RSA", "n": "'"${pubMod64}"'"}}'
# Send header + extended header + payload + signature to the acme-server
data='{"header": '"${header}"', "protected": "'"${protected64}"'", "payload": "'"${payload64}"'", "signature": "'"${signed64}"'"}'
else
# Send extended header + payload + signature to the acme-server
data='{"protected": "'"${protected64}"'", "payload": "'"${payload64}"'", "signature": "'"${signed64}"'"}'
fi
output="$(http_request post "${1}" "${data}")"
if grep -qE "^badnonce " <<< "${output}"; then
echo " ! Request failed (badNonce), retrying request..." >&2
signed_request "${1:-}" "${2:-}" "$(printf "%s" "${output}" | cut -d' ' -f2)"
else
printf "%s" "${output}"
fi
}
# Extracts all subject names from a CSR
# Outputs either the CN, or the SANs, one per line
extract_altnames() {
csrfile="${1}" # path to CSR file
if ! "${OPENSSL}" req -in "${csrfile}" -verify -noout >/dev/null; then
_exiterr "Certificate signing request isn't valid"
fi
reqtext="$("${OPENSSL}" req -in "${csrfile}" -noout -text)"
if <<<"${reqtext}" grep -q '^[[:space:]]*X509v3 Subject Alternative Name:[[:space:]]*$'; then
# SANs used, extract these
altnames="$( <<<"${reqtext}" awk '/X509v3 Subject Alternative Name:/{print;getline;print;}' | tail -n1 )"
# split to one per line:
# shellcheck disable=SC1003
altnames="$( <<<"${altnames}" _sed -e 's/^[[:space:]]*//; s/, /\'$'\n''/g' )"
# we can only get DNS/IP: ones signed
if grep -qEv '^(DNS|IP( Address)*|othername):' <<<"${altnames}"; then
_exiterr "Certificate signing request contains non-DNS/IP Subject Alternative Names"
fi
# strip away the DNS/IP: prefix
altnames="$( <<<"${altnames}" _sed -e 's/^(DNS:|IP( Address)*:|othername:<unsupported>)//' )"
printf "%s" "${altnames}" | tr '\n' ' '
else
# No SANs, extract CN
altnames="$( <<<"${reqtext}" grep '^[[:space:]]*Subject:' | _sed -e 's/.*[ /]CN ?= ?([^ /,]*).*/\1/' )"
printf "%s" "${altnames}"
fi
}
# Get last issuer CN in certificate chain
get_last_cn() {
<<<"${1}" _sed 'H;/-----BEGIN CERTIFICATE-----/h;$!d;x' | "${OPENSSL}" x509 -noout -issuer | head -n1 | _sed -e 's/.*[ /]CN ?= ?([^/,]*).*/\1/'
}
# Create certificate for domain(s) and outputs it FD 3
sign_csr() {
csrfile="${1}" # path to CSR file
if { true >&3; } 2>/dev/null; then
: # fd 3 looks OK
else
_exiterr "sign_csr: FD 3 not open"
fi
shift 1 || true
export altnames="${*}"
if [[ ${API} -eq 1 ]]; then
if [[ -z "${CA_NEW_AUTHZ}" ]] || [[ -z "${CA_NEW_CERT}" ]]; then
_exiterr "Certificate authority doesn't allow certificate signing"
fi
elif [[ ${API} -eq 2 ]] && [[ -z "${CA_NEW_ORDER}" ]]; then
_exiterr "Certificate authority doesn't allow certificate signing"
fi
if [[ -n "${ZSH_VERSION:-}" ]]; then
local -A challenge_names challenge_uris challenge_tokens authorizations keyauths deploy_args
else
local -a challenge_names challenge_uris challenge_tokens authorizations keyauths deploy_args
fi
# Initial step: Find which authorizations we're dealing with
if [[ ${API} -eq 2 ]]; then
# Request new order and store authorization URIs
local challenge_identifiers=""
for altname in ${altnames}; do
if [[ "${altname}" =~ ^ip: ]]; then
challenge_identifiers+="$(printf '{"type": "ip", "value": "%s"}, ' "${altname:3}")"
else
challenge_identifiers+="$(printf '{"type": "dns", "value": "%s"}, ' "${altname}")"
fi
done
challenge_identifiers="[${challenge_identifiers%, }]"
echo " + Requesting new certificate order from CA..."
local order_payload='{"identifiers": '"${challenge_identifiers}"
if [[ -n "${ACME_PROFILE}" ]]; then
order_payload="${order_payload}"',"profile":"'"${ACME_PROFILE}"'"'
fi
order_payload="${order_payload}"'}'
order_location="$(signed_request "${CA_NEW_ORDER}" "${order_payload}" 4>&1 | grep -i ^Location: | cut -d':' -f2- | tr -d ' \t\r\n')"
result="$(signed_request "${order_location}" "" | jsonsh)"
order_authorizations="$(echo "${result}" | get_json_array_values authorizations)"
finalize="$(echo "${result}" | get_json_string_value finalize)"
local idx=0
for uri in ${order_authorizations}; do
authorizations[${idx}]="${uri}"
idx=$((idx+1))
done
echo " + Received ${idx} authorizations URLs from the CA"
else
# Copy $altnames to $authorizations (just doing this to reduce duplicate code later on)
local idx=0
for altname in ${altnames}; do
authorizations[${idx}]="${altname}"
idx=$((idx+1))
done
fi
# Check if authorizations are valid and gather challenge information for pending authorizations
local idx=0
for authorization in ${authorizations[*]}; do
if [[ "${API}" -eq 2 ]]; then
# Receive authorization ($authorization is authz uri)
response="$(signed_request "$(echo "${authorization}" | _sed -e 's/\"(.*)".*/\1/')" "" | jsonsh)"
identifier="$(echo "${response}" | get_json_string_value -p '"identifier","value"')"
identifier_type="$(echo "${response}" | get_json_string_value -p '"identifier","type"')"
echo " + Handling authorization for ${identifier}"
else
# Request new authorization ($authorization is altname)
identifier="${authorization}"
echo " + Requesting authorization for ${identifier}..."
response="$(signed_request "${CA_NEW_AUTHZ}" '{"resource": "new-authz", "identifier": {"type": "dns", "value": "'"${identifier}"'"}}' | jsonsh)"
fi
# Check if authorization has already been validated
if [ "$(echo "${response}" | get_json_string_value status)" = "valid" ]; then
if [ "${PARAM_FORCE_VALIDATION:-no}" = "yes" ]; then
echo " + A valid authorization has been found but will be ignored"
else
echo " + Found valid authorization for ${identifier}"
continue
fi
fi
# Find challenge in authorization
challengeindex="$(echo "${response}" | grep -E '^\["challenges",[0-9]+,"type"\][[:space:]]+"'"${CHALLENGETYPE}"'"' | cut -d',' -f2 || true)"
if [ -z "${challengeindex}" ]; then
allowed_validations="$(echo "${response}" | grep -E '^\["challenges",[0-9]+,"type"\]' | sed -e 's/\[[^\]*\][[:space:]]*//g' -e 's/^"//' -e 's/"$//' | tr '\n' ' ')"
_exiterr "Validating this certificate is not possible using ${CHALLENGETYPE}. Possible validation methods are: ${allowed_validations}"
fi
challenge="$(echo "${response}" | get_json_dict_value -p '"challenges",'"${challengeindex}")"
# Gather challenge information
if [ "${identifier_type:-}" = "ip" ] && [ "${CHALLENGETYPE}" = "tls-alpn-01" ] ; then
challenge_names[${idx}]="$(echo "${identifier}" | ip_to_ptr)"
else
challenge_names[${idx}]="${identifier}"
fi
challenge_tokens[${idx}]="$(echo "${challenge}" | get_json_string_value token)"
if [[ ${API} -eq 2 ]]; then
challenge_uris[${idx}]="$(echo "${challenge}" | get_json_string_value url)"
else
if [[ "$(echo "${challenge}" | get_json_string_value type)" = "urn:acme:error:unauthorized" ]]; then
_exiterr "Challenge unauthorized: $(echo "${challenge}" | get_json_string_value detail)"
fi
challenge_uris[${idx}]="$(echo "${challenge}" | get_json_dict_value validationRecord | get_json_string_value uri)"
fi
# Prepare challenge tokens and deployment parameters
keyauth="${challenge_tokens[${idx}]}.${thumbprint}"
case "${CHALLENGETYPE}" in
"http-01")
# Store challenge response in well-known location and make world-readable (so that a webserver can access it)
printf '%s' "${keyauth}" > "${WELLKNOWN}/${challenge_tokens[${idx}]}"
chmod a+r "${WELLKNOWN}/${challenge_tokens[${idx}]}"
keyauth_hook="${keyauth}"
;;
"dns-01")
# Generate DNS entry content for dns-01 validation
keyauth_hook="$(printf '%s' "${keyauth}" | "${OPENSSL}" dgst -sha256 -binary | urlbase64)"
;;
"tls-alpn-01")
keyauth_hook="$(printf '%s' "${keyauth}" | "${OPENSSL}" dgst -sha256 -c -hex | awk '{print $NF}')"
generate_alpn_certificate "${identifier}" "${identifier_type}" "${keyauth_hook}"
;;
esac
keyauths[${idx}]="${keyauth}"
if [ "${identifier_type:-}" = "ip" ] && [ "${CHALLENGETYPE}" = "tls-alpn-01" ]; then
deploy_args[${idx}]="$(echo "${identifier}" | ip_to_ptr) ${challenge_tokens[${idx}]} ${keyauth_hook}"
else
deploy_args[${idx}]="${identifier} ${challenge_tokens[${idx}]} ${keyauth_hook}"
fi
idx=$((idx+1))
done
local num_pending_challenges=${idx}
echo " + ${num_pending_challenges} pending challenge(s)"
# Deploy challenge tokens
if [[ ${num_pending_challenges} -ne 0 ]]; then
echo " + Deploying challenge tokens..."
if [[ -n "${HOOK}" ]] && [[ "${HOOK_CHAIN}" = "yes" ]]; then
# shellcheck disable=SC2068
"${HOOK}" "deploy_challenge" ${deploy_args[@]} || _exiterr 'deploy_challenge hook returned with non-zero exit code'
elif [[ -n "${HOOK}" ]]; then
# Run hook script to deploy the challenge token
local idx=0
while [ ${idx} -lt ${num_pending_challenges} ]; do
# shellcheck disable=SC2086
"${HOOK}" "deploy_challenge" ${deploy_args[${idx}]} || _exiterr 'deploy_challenge hook returned with non-zero exit code'
idx=$((idx+1))
done
fi
fi
# Validate pending challenges
local idx=0
while [ ${idx} -lt ${num_pending_challenges} ]; do
echo " + Responding to challenge for ${challenge_names[${idx}]} authorization..."
# Ask the acme-server to verify our challenge and wait until it is no longer pending
if [[ ${API} -eq 1 ]]; then
result="$(signed_request "${challenge_uris[${idx}]}" '{"resource": "challenge", "keyAuthorization": "'"${keyauths[${idx}]}"'"}' | jsonsh)"
else
result="$(signed_request "${challenge_uris[${idx}]}" '{}' | jsonsh)"
fi
reqstatus="$(echo "${result}" | get_json_string_value status)"
local waited=0
while [[ "${reqstatus}" = "pending" ]] || [[ "${reqstatus}" = "processing" ]]; do
if [ ${VALIDATION_TIMEOUT} -gt 0 ] && [ ${waited} -gt ${VALIDATION_TIMEOUT} ]; then
_exiterr "Timed out waiting for processing of domain validation (still ${reqstatus})"
fi
echo " + Validation is ${reqstatus}..."
sleep 1
waited=$((waited+1))
if [[ "${API}" -eq 2 ]]; then
result="$(signed_request "${challenge_uris[${idx}]}" "" | jsonsh)"
else
result="$(http_request get "${challenge_uris[${idx}]}" | jsonsh)"
fi
reqstatus="$(echo "${result}" | get_json_string_value status)"
done
[[ "${CHALLENGETYPE}" = "http-01" ]] && rm -f "${WELLKNOWN}/${challenge_tokens[${idx}]}"
[[ "${CHALLENGETYPE}" = "tls-alpn-01" ]] && rm -f "${ALPNCERTDIR}/${challenge_names[${idx}]}.crt.pem" "${ALPNCERTDIR}/${challenge_names[${idx}]}.key.pem"
if [[ "${reqstatus}" = "valid" ]]; then
echo " + Challenge is valid!"
else
[[ -n "${HOOK}" ]] && ("${HOOK}" "invalid_challenge" "${altname}" "${result}" || _exiterr 'invalid_challenge hook returned with non-zero exit code')
break
fi
idx=$((idx+1))
done
if [[ ${num_pending_challenges} -ne 0 ]]; then
echo " + Cleaning challenge tokens..."
# Clean challenge tokens using chained hook
# shellcheck disable=SC2068
[[ -n "${HOOK}" ]] && [[ "${HOOK_CHAIN}" = "yes" ]] && ("${HOOK}" "clean_challenge" ${deploy_args[@]} || _exiterr 'clean_challenge hook returned with non-zero exit code')
# Clean remaining challenge tokens if validation has failed
local idx=0
while [ ${idx} -lt ${num_pending_challenges} ]; do
# Delete challenge file
[[ "${CHALLENGETYPE}" = "http-01" ]] && rm -f "${WELLKNOWN}/${challenge_tokens[${idx}]}"
# Delete alpn verification certificates
[[ "${CHALLENGETYPE}" = "tls-alpn-01" ]] && rm -f "${ALPNCERTDIR}/${challenge_names[${idx}]}.crt.pem" "${ALPNCERTDIR}/${challenge_names[${idx}]}.key.pem"
# Clean challenge token using non-chained hook
# shellcheck disable=SC2086
[[ -n "${HOOK}" ]] && [[ "${HOOK_CHAIN}" != "yes" ]] && ("${HOOK}" "clean_challenge" ${deploy_args[${idx}]} || _exiterr 'clean_challenge hook returned with non-zero exit code')
idx=$((idx+1))
done
if [[ "${reqstatus}" != "valid" ]]; then
echo " + Challenge validation has failed :("
_exiterr "Challenge is invalid! (returned: ${reqstatus}) (result: ${result})"
fi
fi
# Finally request certificate from the acme-server and store it in cert-${timestamp}.pem and link from cert.pem
echo " + Requesting certificate..."
csr64="$("${OPENSSL}" req -in "${csrfile}" -config "${OPENSSL_CNF}" -outform DER | urlbase64)"
if [[ ${API} -eq 1 ]]; then
crt64="$(signed_request "${CA_NEW_CERT}" '{"resource": "new-cert", "csr": "'"${csr64}"'"}' | "${OPENSSL}" base64 -e)"
crt="$( printf -- '-----BEGIN CERTIFICATE-----\n%s\n-----END CERTIFICATE-----\n' "${crt64}" )"
else
result="$(signed_request "${finalize}" '{"csr": "'"${csr64}"'"}' | jsonsh)"
waited=0
while :; do
orderstatus="$(echo "${result}" | get_json_string_value status)"
case "${orderstatus}"
in
"processing" | "pending")
if [ ${ORDER_TIMEOUT} -gt 0 ] && [ ${waited} -gt ${ORDER_TIMEOUT} ]; then
_exiterr "Timed out waiting for processing of order (still ${orderstatus})"
fi
echo " + Order is ${orderstatus}..."
sleep 2;
waited=$((waited+2))
;;
"valid")
break;
;;
*)
_exiterr "Order has invalid/unknown status: ${orderstatus}"
;;
esac
result="$(signed_request "${order_location}" "" | jsonsh)"
done
resheaders="$(_mktemp)"
certificate="$(echo "${result}" | get_json_string_value certificate)"
crt="$(signed_request "${certificate}" "" 4>"${resheaders}")"
if [ -n "${PREFERRED_CHAIN:-}" ]; then
foundaltchain=0
altcn="$(get_last_cn "${crt}")"
altoptions="${altcn}"
if [ "${altcn}" = "${PREFERRED_CHAIN}" ]; then
foundaltchain=1
fi
if [ "${foundaltchain}" = "0" ] && (grep -Ei '^link:' "${resheaders}" | grep -q -Ei 'rel="alternate"'); then
while read -r altcrturl; do
if [ "${foundaltchain}" = "0" ]; then
altcrt="$(signed_request "${altcrturl}" "")"
altcn="$(get_last_cn "${altcrt}")"
altoptions="${altoptions}, ${altcn}"
if [ "${altcn}" = "${PREFERRED_CHAIN}" ]; then
foundaltchain=1
crt="${altcrt}"
fi
fi
done <<< "$(grep -Ei '^link:' "${resheaders}" | grep -Ei 'rel="alternate"' | cut -d'<' -f2 | cut -d'>' -f1)"
fi
if [ "${foundaltchain}" = "0" ]; then
_exiterr "Alternative chain with CN = ${PREFERRED_CHAIN} not found, available options: ${altoptions}"
fi
echo " + Using preferred chain with CN = ${altcn}"
fi
rm -f "${resheaders}"
fi
# Try to load the certificate to detect corruption
echo " + Checking certificate..."
_openssl x509 -text <<<"${crt}"
echo "${crt}" >&3
unset challenge_token
echo " + Done!"
}
# grep issuer cert uri from certificate
get_issuer_cert_uri() {
certificate="${1}"
"${OPENSSL}" x509 -in "${certificate}" -noout -text | (grep 'CA Issuers - URI:' | cut -d':' -f2-) || true
}
get_issuer_hash() {
certificate="${1}"
"${OPENSSL}" x509 -in "${certificate}" -noout -issuer_hash
}
get_ocsp_url() {
certificate="${1}"
"${OPENSSL}" x509 -in "${certificate}" -noout -ocsp_uri
}
# walk certificate chain, retrieving all intermediate certificates
walk_chain() {
local certificate
certificate="${1}"
local issuer_cert_uri
issuer_cert_uri="${2:-}"
if [[ -z "${issuer_cert_uri}" ]]; then issuer_cert_uri="$(get_issuer_cert_uri "${certificate}")"; fi
if [[ -n "${issuer_cert_uri}" ]]; then
# create temporary files
local tmpcert
local tmpcert_raw
tmpcert_raw="$(_mktemp)"
tmpcert="$(_mktemp)"
# download certificate
http_request get "${issuer_cert_uri}" > "${tmpcert_raw}"
# PEM
if grep -q "BEGIN CERTIFICATE" "${tmpcert_raw}"; then mv "${tmpcert_raw}" "${tmpcert}"
# DER
elif "${OPENSSL}" x509 -in "${tmpcert_raw}" -inform DER -out "${tmpcert}" -outform PEM 2> /dev/null > /dev/null; then :
# PKCS7
elif "${OPENSSL}" pkcs7 -in "${tmpcert_raw}" -inform DER -out "${tmpcert}" -outform PEM -print_certs 2> /dev/null > /dev/null; then :
# Unknown certificate type
else _exiterr "Unknown certificate type in chain"
fi
local next_issuer_cert_uri
next_issuer_cert_uri="$(get_issuer_cert_uri "${tmpcert}")"
if [[ -n "${next_issuer_cert_uri}" ]]; then
printf "\n%s\n" "${issuer_cert_uri}"
cat "${tmpcert}"
walk_chain "${tmpcert}" "${next_issuer_cert_uri}"
fi
rm -f "${tmpcert}" "${tmpcert_raw}"
fi
}
# Generate ALPN verification certificate
generate_alpn_certificate() {
local altname="${1}"
local identifier_type="${2}"
local acmevalidation="${3}"
local alpncertdir="${ALPNCERTDIR}"
if [[ ! -e "${alpncertdir}" ]]; then
echo " + Creating new directory ${alpncertdir} ..."
mkdir -p "${alpncertdir}" || _exiterr "Unable to create directory ${alpncertdir}"
fi
echo " + Generating ALPN certificate and key for ${1}..."
tmp_openssl_cnf="$(_mktemp)"
cat "${OPENSSL_CNF}" > "${tmp_openssl_cnf}"
if [[ "${identifier_type}" = "ip" ]]; then
printf "\n[SAN]\nsubjectAltName=IP:%s\n" "${altname}" >> "${tmp_openssl_cnf}"
else
printf "\n[SAN]\nsubjectAltName=DNS:%s\n" "${altname}" >> "${tmp_openssl_cnf}"
fi
printf "1.3.6.1.5.5.7.1.31=critical,DER:04:20:%s\n" "${acmevalidation}" >> "${tmp_openssl_cnf}"
SUBJ="/CN=${altname}/"
[[ "${OSTYPE:0:5}" = "MINGW" ]] && SUBJ="/${SUBJ}"
if [[ "${identifier_type}" = "ip" ]]; then
altname="$(echo "${altname}" | ip_to_ptr)"
fi
_openssl req -x509 -new -sha256 -nodes -newkey rsa:2048 -keyout "${alpncertdir}/${altname}.key.pem" -out "${alpncertdir}/${altname}.crt.pem" -subj "${SUBJ}" -extensions SAN -config "${tmp_openssl_cnf}"
chmod g+r "${alpncertdir}/${altname}.key.pem" "${alpncertdir}/${altname}.crt.pem"
rm -f "${tmp_openssl_cnf}"
}
# Create certificate for domain(s)
sign_domain() {
local certdir="${1}"
shift
timestamp="${1}"
shift
domain="${1}"
altnames="${*}"
export altnames
echo " + Signing domains..."
if [[ ${API} -eq 1 ]]; then
if [[ -z "${CA_NEW_AUTHZ}" ]] || [[ -z "${CA_NEW_CERT}" ]]; then
_exiterr "Certificate authority doesn't allow certificate signing"
fi
elif [[ ${API} -eq 2 ]] && [[ -z "${CA_NEW_ORDER}" ]]; then
_exiterr "Certificate authority doesn't allow certificate signing"
fi
local privkey="privkey.pem"
if [[ ! -e "${certdir}/cert-${timestamp}.csr" ]]; then
# generate a new private key if we need or want one
if [[ ! -r "${certdir}/privkey.pem" ]] || [[ "${PRIVATE_KEY_RENEW}" = "yes" ]]; then
echo " + Generating private key..."
privkey="privkey-${timestamp}.pem"
local tmp_privkey
tmp_privkey="$(_mktemp)"
case "${KEY_ALGO}" in
rsa) _openssl genrsa -out "${tmp_privkey}" "${KEYSIZE}";;
prime256v1|secp384r1) _openssl ecparam -genkey -name "${KEY_ALGO}" -out "${tmp_privkey}" -noout;;
esac
cat "${tmp_privkey}" > "${certdir}/privkey-${timestamp}.pem"
rm "${tmp_privkey}"
fi
# move rolloverkey into position (if any)
if [[ -r "${certdir}/privkey.pem" && -r "${certdir}/privkey.roll.pem" && "${PRIVATE_KEY_RENEW}" = "yes" && "${PRIVATE_KEY_ROLLOVER}" = "yes" ]]; then
echo " + Moving Rolloverkey into position.... "
mv "${certdir}/privkey.roll.pem" "${certdir}/privkey-tmp.pem"
mv "${certdir}/privkey-${timestamp}.pem" "${certdir}/privkey.roll.pem"
mv "${certdir}/privkey-tmp.pem" "${certdir}/privkey-${timestamp}.pem"
fi
# generate a new private rollover key if we need or want one
if [[ ! -r "${certdir}/privkey.roll.pem" && "${PRIVATE_KEY_ROLLOVER}" = "yes" && "${PRIVATE_KEY_RENEW}" = "yes" ]]; then
echo " + Generating private rollover key..."
case "${KEY_ALGO}" in
rsa) _openssl genrsa -out "${certdir}/privkey.roll.pem" "${KEYSIZE}";;
prime256v1|secp384r1) _openssl ecparam -genkey -name "${KEY_ALGO}" -out "${certdir}/privkey.roll.pem" -noout;;
esac
fi
# delete rolloverkeys if disabled
if [[ -r "${certdir}/privkey.roll.pem" && ! "${PRIVATE_KEY_ROLLOVER}" = "yes" ]]; then
echo " + Removing Rolloverkey (feature disabled)..."
rm -f "${certdir}/privkey.roll.pem"
fi
# Generate signing request config and the actual signing request
echo " + Generating signing request..."
SAN=""
for altname in ${altnames}; do
if [[ "${altname}" =~ ^ip: ]]; then
SAN="${SAN}IP:${altname:3}, "
else
SAN="${SAN}DNS:${altname}, "
fi
done
if [[ "${domain}" =~ ^ip: ]]; then
SUBJ="/"
else
SUBJ="/CN=${domain}/"
fi
SAN="${SAN%%, }"
local tmp_openssl_cnf
tmp_openssl_cnf="$(_mktemp)"
cat "${OPENSSL_CNF}" > "${tmp_openssl_cnf}"
printf "\n[SAN]\nsubjectAltName=%s" "${SAN}" >> "${tmp_openssl_cnf}"
if [ "${OCSP_MUST_STAPLE}" = "yes" ]; then
printf "\n1.3.6.1.5.5.7.1.24=DER:30:03:02:01:05" >> "${tmp_openssl_cnf}"
fi
if [[ "${OSTYPE:0:5}" = "MINGW" ]]; then
# The subject starts with a /, so MSYS will assume it's a path and convert
# it unless we escape it with another one:
SUBJ="/${SUBJ}"
fi
"${OPENSSL}" req -new -sha256 -key "${certdir}/${privkey}" -out "${certdir}/cert-${timestamp}.csr" -subj "${SUBJ}" -reqexts SAN -config "${tmp_openssl_cnf}"
rm -f "${tmp_openssl_cnf}"
fi
crt_path="${certdir}/cert-${timestamp}.pem"
# shellcheck disable=SC2086
sign_csr "${certdir}/cert-${timestamp}.csr" ${altnames} 3>"${crt_path}"
# Create fullchain.pem
echo " + Creating fullchain.pem..."
if [[ ${API} -eq 1 ]]; then
cat "${crt_path}" > "${certdir}/fullchain-${timestamp}.pem"
local issuer_hash
issuer_hash="$(get_issuer_hash "${crt_path}")"
if [ -e "${CHAINCACHE}/${issuer_hash}.chain" ]; then
echo " + Using cached chain!"
cat "${CHAINCACHE}/${issuer_hash}.chain" > "${certdir}/chain-${timestamp}.pem"
else
echo " + Walking chain..."
local issuer_cert_uri
issuer_cert_uri="$(get_issuer_cert_uri "${crt_path}" || echo "unknown")"
(walk_chain "${crt_path}" > "${certdir}/chain-${timestamp}.pem") || _exiterr "Walking chain has failed, your certificate has been created and can be found at ${crt_path}, the corresponding private key at ${privkey}. If you want you can manually continue on creating and linking all necessary files. If this error occurs again you should manually generate the certificate chain and place it under ${CHAINCACHE}/${issuer_hash}.chain (see ${issuer_cert_uri})"
cat "${certdir}/chain-${timestamp}.pem" > "${CHAINCACHE}/${issuer_hash}.chain"
fi
cat "${certdir}/chain-${timestamp}.pem" >> "${certdir}/fullchain-${timestamp}.pem"
else
tmpcert="$(_mktemp)"
tmpchain="$(_mktemp)"
awk '{print >out}; /----END CERTIFICATE-----/{out=tmpchain}' out="${tmpcert}" tmpchain="${tmpchain}" "${certdir}/cert-${timestamp}.pem"
mv "${certdir}/cert-${timestamp}.pem" "${certdir}/fullchain-${timestamp}.pem"
cat "${tmpcert}" > "${certdir}/cert-${timestamp}.pem"
cat "${tmpchain}" > "${certdir}/chain-${timestamp}.pem"
rm "${tmpcert}" "${tmpchain}"
fi
# Wait for hook script to sync the files before creating the symlinks
[[ -n "${HOOK}" ]] && ("${HOOK}" "sync_cert" "${certdir}/privkey-${timestamp}.pem" "${certdir}/cert-${timestamp}.pem" "${certdir}/fullchain-${timestamp}.pem" "${certdir}/chain-${timestamp}.pem" "${certdir}/cert-${timestamp}.csr" || _exiterr 'sync_cert hook returned with non-zero exit code')
# Update symlinks
[[ "${privkey}" = "privkey.pem" ]] || ln -sf "privkey-${timestamp}.pem" "${certdir}/privkey.pem"
ln -sf "chain-${timestamp}.pem" "${certdir}/chain.pem"
ln -sf "fullchain-${timestamp}.pem" "${certdir}/fullchain.pem"
ln -sf "cert-${timestamp}.csr" "${certdir}/cert.csr"
ln -sf "cert-${timestamp}.pem" "${certdir}/cert.pem"
# Wait for hook script to clean the challenge and to deploy cert if used
[[ -n "${HOOK}" ]] && ("${HOOK}" "deploy_cert" "${domain}" "${certdir}/privkey.pem" "${certdir}/cert.pem" "${certdir}/fullchain.pem" "${certdir}/chain.pem" "${timestamp}" || _exiterr 'deploy_cert hook returned with non-zero exit code')
unset challenge_token
echo " + Done!"
}
# Update OCSP stapling file
update_ocsp_stapling() {
local certdir="${1}"
local update_ocsp="${2}"
local cert="${3}"
local chain="${4}"
local ocsp_url="$(get_ocsp_url "${cert}")"
if [[ -z "${ocsp_url}" ]]; then
echo " ! ERROR: OCSP stapling requested but no OCSP url found in certificate." >&2
echo " ! Keep in mind that some CAs ended support for OCSP: https://letsencrypt.org/2024/12/05/ending-ocsp/" >&2
return 1
fi
if [[ ! -e "${certdir}/ocsp.der" ]]; then
update_ocsp="yes"
elif ! ("${OPENSSL}" ocsp -no_nonce -issuer "${chain}" -verify_other "${chain}" -cert "${cert}" -respin "${certdir}/ocsp.der" -status_age $((OCSP_DAYS*24*3600)) 2>&1 | grep -q "${cert}: good"); then
update_ocsp="yes"
fi
if [[ "${update_ocsp}" = "yes" ]]; then
echo " + Updating OCSP stapling file"
ocsp_timestamp="$(date +%s)"
if grep -qE "^(openssl (0|(1\.0))\.)|(libressl (1|2|3)\.)" <<< "$(${OPENSSL} version | awk '{print tolower($0)}')"; then
ocsp_log="$("${OPENSSL}" ocsp -no_nonce -issuer "${chain}" -verify_other "${chain}" -cert "${cert}" -respout "${certdir}/ocsp-${ocsp_timestamp}.der" -url "${ocsp_url}" -header "HOST" "$(echo "${ocsp_url}" | _sed -e 's/^http(s?):\/\///' -e 's/\/.*$//g')" 2>&1)" || _exiterr "Fetching of OCSP information failed. Please note that some CAs (e.g. LetsEncrypt) do no longer support OCSP. Error message: ${ocsp_log}"
else
ocsp_log="$("${OPENSSL}" ocsp -no_nonce -issuer "${chain}" -verify_other "${chain}" -cert "${cert}" -respout "${certdir}/ocsp-${ocsp_timestamp}.der" -url "${ocsp_url}" 2>&1)" || _exiterr "Fetching of OCSP information failed. Please note that some CAs (e.g. LetsEncrypt) do no longer support OCSP. Error message: ${ocsp_log}"
fi
ln -sf "ocsp-${ocsp_timestamp}.der" "${certdir}/ocsp.der"
[[ -n "${HOOK}" ]] && (altnames="${domain} ${morenames}" "${HOOK}" "deploy_ocsp" "${domain}" "${certdir}/ocsp.der" "${ocsp_timestamp}" || _exiterr 'deploy_ocsp hook returned with non-zero exit code')
else
echo " + OCSP stapling file is still valid (skipping update)"
fi
}
# Usage: --version (-v)
# Description: Print version information
command_version() {
load_config noverify
echo "Dehydrated by Lukas Schauer"
echo "https://dehydrated.io"
echo ""
echo "Dehydrated version: ${VERSION}"
revision="$(cd "${SCRIPTDIR}"; git rev-parse HEAD 2>/dev/null || echo "unknown")"
echo "GIT-Revision: ${revision}"
echo ""
# shellcheck disable=SC1091
if [[ "${OSTYPE}" =~ (BSD|Darwin) ]]; then
echo "OS: $(uname -sr)"
elif [[ -e /etc/os-release ]]; then
( . /etc/os-release && echo "OS: $PRETTY_NAME" )
elif [[ -e /usr/lib/os-release ]]; then
( . /usr/lib/os-release && echo "OS: $PRETTY_NAME" )
else
echo "OS: $(grep -v '^$' /etc/issue | head -n1 | _sed 's/\\(r|n|l) .*//g')"
fi
echo "Used software:"
[[ -n "${BASH_VERSION:-}" ]] && echo " bash: ${BASH_VERSION}"
[[ -n "${ZSH_VERSION:-}" ]] && echo " zsh: ${ZSH_VERSION}"
echo " curl: ${CURL_VERSION}"
if [[ "${OSTYPE}" =~ (BSD|Darwin) ]]; then
echo " awk, sed, mktemp, grep, diff: BSD base system versions"
else
echo " awk: $(awk -W version 2>&1 | head -n1)"
echo " sed: $(sed --version 2>&1 | head -n1)"
echo " mktemp: $(mktemp --version 2>&1 | head -n1)"
echo " grep: $(grep --version 2>&1 | head -n1)"
echo " diff: $(diff --version 2>&1 | head -n1)"
fi
echo " openssl: $("${OPENSSL}" version 2>&1)"
exit 0
}
# Usage: --display-terms
# Description: Display current terms of service
command_terms() {
init_system
echo "The current terms of service: $CA_TERMS"
echo "+ Done!"
exit 0
}
# Usage: --register
# Description: Register account key
command_register() {
init_system
echo "+ Done!"
exit 0
}
# Usage: --account
# Description: Update account contact information
command_account() {
init_system
FAILED=false
NEW_ACCOUNT_KEY_JSON="$(_mktemp)"
# Check if we have the registration url
if [[ -z "${ACCOUNT_URL}" ]]; then
_exiterr "Error retrieving registration url."
fi
echo "+ Updating registration url: ${ACCOUNT_URL} contact information..."
if [[ ${API} -eq 1 ]]; then
# If an email for the contact has been provided then adding it to the registered account
if [[ -n "${CONTACT_EMAIL}" ]]; then
(signed_request "${ACCOUNT_URL}" '{"resource": "reg", "contact":["mailto:'"${CONTACT_EMAIL}"'"]}' > "${NEW_ACCOUNT_KEY_JSON}") || FAILED=true
else
(signed_request "${ACCOUNT_URL}" '{"resource": "reg", "contact":[]}' > "${NEW_ACCOUNT_KEY_JSON}") || FAILED=true
fi
else
# If an email for the contact has been provided then adding it to the registered account
if [[ -n "${CONTACT_EMAIL}" ]]; then
(signed_request "${ACCOUNT_URL}" '{"contact":["mailto:'"${CONTACT_EMAIL}"'"]}' > "${NEW_ACCOUNT_KEY_JSON}") || FAILED=true
else
(signed_request "${ACCOUNT_URL}" '{"contact":[]}' > "${NEW_ACCOUNT_KEY_JSON}") || FAILED=true
fi
fi
if [[ "${FAILED}" = "true" ]]; then
rm "${NEW_ACCOUNT_KEY_JSON}"
_exiterr "Error updating account information. See message above for more information."
fi
if diff -q "${NEW_ACCOUNT_KEY_JSON}" "${ACCOUNT_KEY_JSON}" > /dev/null; then
echo "+ Account information was the same after the update"
rm "${NEW_ACCOUNT_KEY_JSON}"
else
ACCOUNT_KEY_JSON_BACKUP="${ACCOUNT_KEY_JSON%.*}-$(date +%s).json"
echo "+ Backup ${ACCOUNT_KEY_JSON} as ${ACCOUNT_KEY_JSON_BACKUP}"
cp -p "${ACCOUNT_KEY_JSON}" "${ACCOUNT_KEY_JSON_BACKUP}"
echo "+ Populate ${ACCOUNT_KEY_JSON}"
mv "${NEW_ACCOUNT_KEY_JSON}" "${ACCOUNT_KEY_JSON}"
fi
echo "+ Done!"
exit 0
}
# Parse contents of domains.txt and domains.txt.d
parse_domains_txt() {
# Allow globbing temporarily
noglob_set
local inputs=("${DOMAINS_TXT}" "${DOMAINS_TXT}.d"/*.txt)
noglob_clear
cat "${inputs[@]}" |
tr -d '\r' |
awk '{print tolower($0)}' |
_sed -e 's/^[[:space:]]*//g' -e 's/[[:space:]]*$//g' -e 's/[[:space:]]+/ /g' -e 's/([^ ])>/\1 >/g' -e 's/> />/g' |
(grep -vE '^(#|$)' || true)
}
# Usage: --cron (-c)
# Description: Sign/renew non-existent/changed/expiring certificates.
command_sign_domains() {
init_system
hookscript_bricker_hook
# Call startup hook
[[ -n "${HOOK}" ]] && ("${HOOK}" "startup_hook" || _exiterr 'startup_hook hook returned with non-zero exit code')
if [ ! -d "${CHAINCACHE}" ]; then
echo " + Creating chain cache directory ${CHAINCACHE}"
mkdir "${CHAINCACHE}"
fi
if [[ -n "${PARAM_DOMAIN:-}" ]]; then
DOMAINS_TXT="$(_mktemp)"
if [[ -n "${PARAM_ALIAS:-}" ]]; then
printf "%s > %s" "${PARAM_DOMAIN}" "${PARAM_ALIAS}" > "${DOMAINS_TXT}"
else
printf "%s" "${PARAM_DOMAIN}" > "${DOMAINS_TXT}"
fi
elif [[ -e "${DOMAINS_TXT}" ]]; then
if [[ ! -r "${DOMAINS_TXT}" ]]; then
_exiterr "domains.txt found but not readable"
fi
else
_exiterr "domains.txt not found and --domain not given"
fi
# Generate certificates for all domains found in domains.txt. Check if existing certificate are about to expire
ORIGIFS="${IFS}"
IFS=$'\n'
for line in $(parse_domains_txt); do
reset_configvars
IFS="${ORIGIFS}"
alias="$(grep -Eo '>[^ ]+' <<< "${line}" || true)"
line="$(_sed -e 's/>[^ ]+[ ]*//g' <<< "${line}")"
aliascount="$(grep -Eo '>' <<< "${alias}" | awk 'END {print NR}' || true )"
[ "${aliascount}" -gt 1 ] && _exiterr "Only one alias per line is allowed in domains.txt!"
domain="$(printf '%s\n' "${line}" | cut -d' ' -f1)"
morenames="$(printf '%s\n' "${line}" | cut -s -d' ' -f2-)"
[ "${aliascount}" -lt 1 ] && alias="${domain}" || alias="${alias#>}"
export alias
if [[ -z "${morenames}" ]];then
echo "Processing ${domain}"
else
echo "Processing ${domain} with alternative names: ${morenames}"
fi
if [ "${alias:0:2}" = "*." ]; then
_exiterr "Please define a valid alias for your ${domain} wildcard-certificate. See domains.txt-documentation for more details."
fi
local certdir="${CERTDIR}/${alias}"
cert="${certdir}/cert.pem"
chain="${certdir}/chain.pem"
force_renew="${PARAM_FORCE:-no}"
timestamp="$(date +%s)"
# If there is no existing certificate directory => make it
if [[ ! -e "${certdir}" ]]; then
echo " + Creating new directory ${certdir} ..."
mkdir -p "${certdir}" || _exiterr "Unable to create directory ${certdir}"
fi
# read cert config
# for now this loads the certificate specific config in a subshell and parses a diff of set variables.
# we could just source the config file but i decided to go this way to protect people from accidentally overriding
# variables used internally by this script itself.
if [[ -n "${DOMAINS_D}" ]]; then
certconfig="${DOMAINS_D}/${alias}"
else
certconfig="${certdir}/config"
fi
if [ -f "${certconfig}" ]; then
echo " + Using certificate specific config file!"
ORIGIFS="${IFS}"
IFS=$'\n'
for cfgline in $(
beforevars="$(_mktemp)"
aftervars="$(_mktemp)"
set > "${beforevars}"
# shellcheck disable=SC1090
. "${certconfig}"
set > "${aftervars}"
diff -u "${beforevars}" "${aftervars}" | grep -E '^\+[^+]'
rm "${beforevars}"
rm "${aftervars}"
); do
config_var="$(echo "${cfgline:1}" | cut -d'=' -f1)"
config_value="$(echo "${cfgline:1}" | cut -d'=' -f2- | tr -d "'")"
# All settings that are allowed here should also be stored and
# restored in store_configvars() and reset_configvars()
case "${config_var}" in
KEY_ALGO|OCSP_MUST_STAPLE|OCSP_FETCH|OCSP_DAYS|PRIVATE_KEY_RENEW|PRIVATE_KEY_ROLLOVER|KEYSIZE|CHALLENGETYPE|HOOK|PREFERRED_CHAIN|WELLKNOWN|HOOK_CHAIN|OPENSSL_CNF|RENEW_DAYS|ACME_PROFILE|ORDER_TIMEOUT|VALIDATION_TIMEOUT|KEEP_GOING)
echo " + ${config_var} = ${config_value}"
declare -- "${config_var}=${config_value}"
;;
_) ;;
*) echo " ! Setting ${config_var} on a per-certificate base is not (yet) supported" >&2
esac
done
IFS="${ORIGIFS}"
fi
verify_config
hookscript_bricker_hook
export WELLKNOWN CHALLENGETYPE KEY_ALGO PRIVATE_KEY_ROLLOVER
skip="no"
# Allow for external CSR generation
local csrfile=""
if [[ -n "${HOOK}" ]]; then
csr="$("${HOOK}" "generate_csr" "${domain}" "${certdir}" "${domain} ${morenames}")" || _exiterr 'generate_csr hook returned with non-zero exit code'
if grep -qE "\-----BEGIN (NEW )?CERTIFICATE REQUEST-----" <<< "${csr}"; then
csrfile="$(_mktemp)"
cat > "${csrfile}" <<< "${csr}"
altnames="$(extract_altnames "${csrfile}")"
domain="$(cut -d' ' -f1 <<< "${altnames}")"
morenames="$(cut -s -d' ' -f2- <<< "${altnames}")"
echo " + Using CSR from hook script (real names: ${altnames})"
else
csrfile=""
fi
fi
# Check domain names of existing certificate
if [[ -e "${cert}" && "${force_renew}" = "no" ]]; then
printf " + Checking domain name(s) of existing cert..."
certnames="$("${OPENSSL}" x509 -in "${cert}" -text -noout | grep -E '(DNS|IP( Address*)):' | _sed 's/(DNS|IP( Address)*)://g' | tr -d ' ' | tr ',' '\n' | sort -u | tr '\n' ' ' | _sed 's/ $//')"
givennames="$(echo "${domain}" "${morenames}"| tr ' ' '\n' | sort -u | tr '\n' ' ' | _sed 's/ip://g' | _sed 's/ $//' | _sed 's/^ //')"
if [[ "${certnames}" = "${givennames}" ]]; then
echo " unchanged."
else
echo " changed!"
echo " + Domain name(s) are not matching!"
echo " + Names in old certificate: ${certnames}"
echo " + Configured names: ${givennames}"
echo " + Forcing renew."
force_renew="yes"
fi
fi
# Check expire date of existing certificate
if [[ -e "${cert}" ]]; then
echo " + Checking expire date of existing cert..."
valid="$("${OPENSSL}" x509 -enddate -noout -in "${cert}" | cut -d= -f2- )"
printf " + Valid till %s " "${valid}"
if ("${OPENSSL}" x509 -checkend $((RENEW_DAYS * 86400)) -noout -in "${cert}" > /dev/null 2>&1); then
printf "(Longer than %d days). " "${RENEW_DAYS}"
if [[ "${force_renew}" = "yes" ]]; then
echo "Ignoring because renew was forced!"
else
# Certificate-Names unchanged and cert is still valid
echo "Skipping renew!"
[[ -n "${HOOK}" ]] && ("${HOOK}" "unchanged_cert" "${domain}" "${certdir}/privkey.pem" "${certdir}/cert.pem" "${certdir}/fullchain.pem" "${certdir}/chain.pem" || _exiterr 'unchanged_cert hook returned with non-zero exit code')
skip="yes"
fi
else
echo "(Less than ${RENEW_DAYS} days). Renewing!"
fi
fi
local update_ocsp
update_ocsp="no"
# Sign certificate for this domain
if [[ ! "${skip}" = "yes" ]]; then
update_ocsp="yes"
if [[ -n "${csrfile}" ]]; then
cat "${csrfile}" > "${certdir}/cert-${timestamp}.csr"
rm "${csrfile}"
fi
# shellcheck disable=SC2086
if [[ "${KEEP_GOING:-}" = "yes" ]]; then
skip_exit_hook=yes
sign_domain "${certdir}" "${timestamp}" "${domain}" ${morenames} &
wait $! || exit_with_errorcode=1
skip_exit_hook=no
else
sign_domain "${certdir}" "${timestamp}" "${domain}" ${morenames}
fi
fi
if [[ "${OCSP_FETCH}" = "yes" ]]; then
if [[ "${KEEP_GOING:-}" = "yes" ]]; then
skip_exit_hook=yes
update_ocsp_stapling "${certdir}" "${update_ocsp}" "${cert}" "${chain}" &
wait $! || exit_with_errorcode=1
skip_exit_hook=no
else
update_ocsp_stapling "${certdir}" "${update_ocsp}" "${cert}" "${chain}"
fi
fi
done
reset_configvars
# remove temporary domains.txt file if used
[[ -n "${PARAM_DOMAIN:-}" ]] && rm -f "${DOMAINS_TXT}"
[[ -n "${HOOK}" ]] && ("${HOOK}" "exit_hook" || echo 'exit_hook returned with non-zero exit code!' >&2)
if [[ "${AUTO_CLEANUP}" == "yes" ]]; then
echo " + Running automatic cleanup"
PARAM_CLEANUPDELETE="${AUTO_CLEANUP_DELETE:-no}" command_cleanup noinit | _sed 's/^/ + /g'
fi
exit "${exit_with_errorcode}"
}
# Usage: --signcsr (-s) path/to/csr.pem
# Description: Sign a given CSR, output CRT on stdout (advanced usage)
command_sign_csr() {
init_system
# redirect stdout to stderr
# leave stdout over at fd 3 to output the cert
exec 3>&1 1>&2
# load csr
local csrfile="${1}"
if [ ! -r "${csrfile}" ]; then
_exiterr "Could not read certificate signing request ${csrfile}"
fi
# extract names
altnames="$(extract_altnames "${csrfile}")"
# gen cert
certfile="$(_mktemp)"
# shellcheck disable=SC2086
sign_csr "${csrfile}" ${altnames} 3> "${certfile}"
# print cert
echo "# CERT #" >&3
cat "${certfile}" >&3
echo >&3
# print chain
if [ -n "${PARAM_FULL_CHAIN:-}" ]; then
# get and convert ca cert
chainfile="$(_mktemp)"
tmpchain="$(_mktemp)"
http_request get "$("${OPENSSL}" x509 -in "${certfile}" -noout -text | grep 'CA Issuers - URI:' | cut -d':' -f2-)" > "${tmpchain}"
if grep -q "BEGIN CERTIFICATE" "${tmpchain}"; then
mv "${tmpchain}" "${chainfile}"
else
"${OPENSSL}" x509 -in "${tmpchain}" -inform DER -out "${chainfile}" -outform PEM
rm "${tmpchain}"
fi
echo "# CHAIN #" >&3
cat "${chainfile}" >&3
rm "${chainfile}"
fi
# cleanup
rm "${certfile}"
exit 0
}
# Usage: --revoke (-r) path/to/cert.pem
# Description: Revoke specified certificate
command_revoke() {
init_system
[[ -n "${CA_REVOKE_CERT}" ]] || _exiterr "Certificate authority doesn't allow certificate revocation."
cert="${1}"
if [[ -L "${cert}" ]]; then
# follow symlink and use real certificate name (so we move the real file and not the symlink at the end)
local link_target
link_target="$(readlink -n "${cert}")"
if [[ "${link_target}" =~ ^/ ]]; then
cert="${link_target}"
else
cert="$(dirname "${cert}")/${link_target}"
fi
fi
[[ -f "${cert}" ]] || _exiterr "Could not find certificate ${cert}"
echo "Revoking ${cert}"
cert64="$("${OPENSSL}" x509 -in "${cert}" -inform PEM -outform DER | urlbase64)"
if [[ ${API} -eq 1 ]]; then
response="$(signed_request "${CA_REVOKE_CERT}" '{"resource": "revoke-cert", "certificate": "'"${cert64}"'"}' | clean_json)"
else
response="$(signed_request "${CA_REVOKE_CERT}" '{"certificate": "'"${cert64}"'"}' | clean_json)"
fi
# if there is a problem with our revoke request _request (via signed_request) will report this and "exit 1" out
# so if we are here, it is safe to assume the request was successful
echo " + Done."
echo " + Renaming certificate to ${cert}-revoked"
mv -f "${cert}" "${cert}-revoked"
}
# Usage: --deactivate
# Description: Deactivate account
command_deactivate() {
init_system
echo "Deactivating account ${ACCOUNT_URL}"
if [[ ${API} -eq 1 ]]; then
echo "Deactivation for ACMEv1 is not implemented"
else
response="$(signed_request "${ACCOUNT_URL}" '{"status": "deactivated"}' | clean_json)"
deactstatus=$(echo "$response" | jsonsh | get_json_string_value "status")
if [[ "${deactstatus}" = "deactivated" ]]; then
touch "${ACCOUNT_DEACTIVATED}"
else
_exiterr "Account deactivation failed!"
fi
fi
echo " + Done."
}
# Usage: --cleanup (-gc)
# Description: Move unused certificate files to archive directory
command_cleanup() {
if [ ! "${1:-}" = "noinit" ]; then
load_config
fi
if [[ ! "${PARAM_CLEANUPDELETE:-}" = "yes" ]]; then
# Create global archive directory if not existent
if [[ ! -e "${BASEDIR}/archive" ]]; then
mkdir "${BASEDIR}/archive"
fi
fi
# Allow globbing
noglob_set
# Loop over all certificate directories
for certdir in "${CERTDIR}/"*; do
# Skip if entry is not a folder
[[ -d "${certdir}" ]] || continue
# Get certificate name
certname="$(basename "${certdir}")"
# Create certificates archive directory if not existent
if [[ ! "${PARAM_CLEANUPDELETE:-}" = "yes" ]]; then
archivedir="${BASEDIR}/archive/${certname}"
if [[ ! -e "${archivedir}" ]]; then
mkdir "${archivedir}"
fi
fi
# Loop over file-types (certificates, keys, signing-requests, ...)
for filetype in cert.csr cert.pem chain.pem fullchain.pem privkey.pem ocsp.der; do
# Delete all if symlink is broken
if [[ -r "${certdir}/${filetype}" ]]; then
# Look up current file in use
current="$(basename "$(readlink "${certdir}/${filetype}")")"
else
if [[ -h "${certdir}/${filetype}" ]]; then
echo "Removing broken symlink: ${certdir}/${filetype}"
rm -f "${certdir}/${filetype}"
fi
current=""
fi
# Split filetype into name and extension
filebase="$(echo "${filetype}" | cut -d. -f1)"
fileext="$(echo "${filetype}" | cut -d. -f2)"
# Loop over all files of this type
for file in "${certdir}/${filebase}-"*".${fileext}" "${certdir}/${filebase}-"*".${fileext}-revoked"; do
# Check if current file is in use, if unused move to archive directory
filename="$(basename "${file}")"
if [[ ! "${filename}" = "${current}" ]] && [[ -f "${certdir}/${filename}" ]]; then
if [[ "${PARAM_CLEANUPDELETE:-}" = "yes" ]]; then
echo "Deleting unused file: ${certname}/${filename}"
rm "${certdir}/${filename}"
else
echo "Moving unused file to archive directory: ${certname}/${filename}"
mv "${certdir}/${filename}" "${archivedir}/${filename}"
fi
fi
done
done
done
exit "${exit_with_errorcode}"
}
# Usage: --cleanup-delete (-gcd)
# Description: Deletes (!) unused certificate files
command_cleanupdelete() {
command_cleanup
}
# Usage: --help (-h)
# Description: Show help text
command_help() {
printf "Usage: %s [-h] [command [argument]] [parameter [argument]] [parameter [argument]] ...\n\n" "${0}"
printf "Default command: help\n\n"
echo "Commands:"
grep -e '^[[:space:]]*# Usage:' -e '^[[:space:]]*# Description:' -e '^command_.*()[[:space:]]*{' "${0}" | while read -r usage; read -r description; read -r command; do
if [[ ! "${usage}" =~ Usage ]] || [[ ! "${description}" =~ Description ]] || [[ ! "${command}" =~ ^command_ ]]; then
_exiterr "Error generating help text."
fi
printf " %-32s %s\n" "${usage##"# Usage: "}" "${description##"# Description: "}"
done
printf -- "\nParameters:\n"
grep -E -e '^[[:space:]]*# PARAM_Usage:' -e '^[[:space:]]*# PARAM_Description:' "${0}" | while read -r usage; read -r description; do
if [[ ! "${usage}" =~ Usage ]] || [[ ! "${description}" =~ Description ]]; then
_exiterr "Error generating help text."
fi
printf " %-32s %s\n" "${usage##"# PARAM_Usage: "}" "${description##"# PARAM_Description: "}"
done
}
# Usage: --env (-e)
# Description: Output configuration variables for use in other scripts
command_env() {
echo "# dehydrated configuration"
load_config
typeset -p CA CERTDIR ALPNCERTDIR CHALLENGETYPE DOMAINS_D DOMAINS_TXT HOOK HOOK_CHAIN RENEW_DAYS ACCOUNT_KEY ACCOUNT_KEY_JSON ACCOUNT_ID_JSON KEYSIZE WELLKNOWN PRIVATE_KEY_RENEW OPENSSL_CNF CONTACT_EMAIL LOCKFILE
}
# Main method (parses script arguments and calls command_* methods)
main() {
exit_with_errorcode=0
skip_exit_hook=no
COMMAND=""
set_command() {
[[ -z "${COMMAND}" ]] || _exiterr "Only one command can be executed at a time. See help (-h) for more information."
COMMAND="${1}"
}
check_parameters() {
if [[ -z "${1:-}" ]]; then
echo "The specified command requires additional parameters. See help:" >&2
echo >&2
command_help >&2
exit 1
elif [[ "${1:0:1}" = "-" ]]; then
_exiterr "Invalid argument: ${1}"
fi
}
[[ -z "${*}" ]] && eval set -- "--help"
while (( ${#} )); do
case "${1}" in
--help|-h)
command_help
exit 0
;;
--env|-e)
set_command env
;;
--cron|-c)
set_command sign_domains
;;
--register)
set_command register
;;
--account)
set_command account
;;
# PARAM_Usage: --accept-terms
# PARAM_Description: Accept CAs terms of service
--accept-terms)
PARAM_ACCEPT_TERMS="yes"
;;
--display-terms)
set_command terms
;;
--signcsr|-s)
shift 1
set_command sign_csr
check_parameters "${1:-}"
PARAM_CSR="${1}"
;;
--revoke|-r)
shift 1
set_command revoke
check_parameters "${1:-}"
PARAM_REVOKECERT="${1}"
;;
--deactivate)
set_command deactivate
;;
--version|-v)
set_command version
;;
--cleanup|-gc)
set_command cleanup
;;
--cleanup-delete|-gcd)
set_command cleanupdelete
PARAM_CLEANUPDELETE="yes"
;;
# PARAM_Usage: --full-chain (-fc)
# PARAM_Description: Print full chain when using --signcsr
--full-chain|-fc)
PARAM_FULL_CHAIN="1"
;;
# PARAM_Usage: --ipv4 (-4)
# PARAM_Description: Resolve names to IPv4 addresses only
--ipv4|-4)
PARAM_IP_VERSION="4"
;;
# PARAM_Usage: --ipv6 (-6)
# PARAM_Description: Resolve names to IPv6 addresses only
--ipv6|-6)
PARAM_IP_VERSION="6"
;;
# PARAM_Usage: --domain (-d) domain.tld
# PARAM_Description: Use specified domain name(s) instead of domains.txt entry (one certificate!)
--domain|-d)
shift 1
check_parameters "${1:-}"
if [[ -z "${PARAM_DOMAIN:-}" ]]; then
PARAM_DOMAIN="${1}"
else
PARAM_DOMAIN="${PARAM_DOMAIN} ${1}"
fi
;;
# PARAM_Usage: --ca url/preset
# PARAM_Description: Use specified CA URL or preset
--ca)
shift 1
check_parameters "${1:-}"
[[ -n "${PARAM_CA:-}" ]] && _exiterr "CA can only be specified once!"
PARAM_CA="${1}"
;;
# PARAM_Usage: --alias certalias
# PARAM_Description: Use specified name for certificate directory (and per-certificate config) instead of the primary domain (only used if --domain is specified)
--alias)
shift 1
check_parameters "${1:-}"
[[ -n "${PARAM_ALIAS:-}" ]] && _exiterr "Alias can only be specified once!"
PARAM_ALIAS="${1}"
;;
# PARAM_Usage: --keep-going (-g)
# PARAM_Description: Keep going after encountering an error while creating/renewing multiple certificates in cron mode
--keep-going|-g)
PARAM_KEEP_GOING="yes"
;;
# PARAM_Usage: --force (-x)
# PARAM_Description: Force certificate renewal even if it is not due to expire within RENEW_DAYS
--force|-x)
PARAM_FORCE="yes"
;;
# PARAM_Usage: --force-validation
# PARAM_Description: Force revalidation of domain names (used in combination with --force)
--force-validation)
PARAM_FORCE_VALIDATION="yes"
;;
# PARAM_Usage: --no-lock (-n)
# PARAM_Description: Don't use lockfile (potentially dangerous!)
--no-lock|-n)
PARAM_NO_LOCK="yes"
;;
# PARAM_Usage: --lock-suffix example.com
# PARAM_Description: Suffix lockfile name with a string (useful for with -d)
--lock-suffix)
shift 1
check_parameters "${1:-}"
PARAM_LOCKFILE_SUFFIX="${1}"
;;
# PARAM_Usage: --ocsp
# PARAM_Description: Sets option in CSR indicating OCSP stapling to be mandatory
--ocsp)
PARAM_OCSP_MUST_STAPLE="yes"
;;
# PARAM_Usage: --privkey (-p) path/to/key.pem
# PARAM_Description: Use specified private key instead of account key (useful for revocation)
--privkey|-p)
shift 1
check_parameters "${1:-}"
PARAM_ACCOUNT_KEY="${1}"
;;
# PARAM_Usage: --domains-txt path/to/domains.txt
# PARAM_Description: Use specified domains.txt instead of default/configured one
--domains-txt)
shift 1
check_parameters "${1:-}"
PARAM_DOMAINS_TXT="${1}"
;;
# PARAM_Usage: --config (-f) path/to/config
# PARAM_Description: Use specified config file
--config|-f)
shift 1
check_parameters "${1:-}"
CONFIG="${1}"
;;
# PARAM_Usage: --hook (-k) path/to/hook.sh
# PARAM_Description: Use specified script for hooks
--hook|-k)
shift 1
check_parameters "${1:-}"
PARAM_HOOK="${1}"
;;
# PARAM_Usage: --preferred-chain issuer-cn
# PARAM_Description: Use alternative certificate chain identified by issuer CN
--preferred-chain)
shift 1
check_parameters "${1:-}"
PARAM_PREFERRED_CHAIN="${1}"
;;
# PARAM_Usage: --out (-o) certs/directory
# PARAM_Description: Output certificates into the specified directory
--out|-o)
shift 1
check_parameters "${1:-}"
PARAM_CERTDIR="${1}"
;;
# PARAM_Usage: --alpn alpn-certs/directory
# PARAM_Description: Output alpn verification certificates into the specified directory
--alpn)
shift 1
check_parameters "${1:-}"
PARAM_ALPNCERTDIR="${1}"
;;
# PARAM_Usage: --challenge (-t) http-01|dns-01|tls-alpn-01
# PARAM_Description: Which challenge should be used? Currently http-01, dns-01, and tls-alpn-01 are supported
--challenge|-t)
shift 1
check_parameters "${1:-}"
PARAM_CHALLENGETYPE="${1}"
;;
# PARAM_Usage: --algo (-a) rsa|prime256v1|secp384r1
# PARAM_Description: Which public key algorithm should be used? Supported: rsa, prime256v1 and secp384r1
--algo|-a)
shift 1
check_parameters "${1:-}"
PARAM_KEY_ALGO="${1}"
;;
# PARAM_Usage: --acme-profile profile_name
# PARAM_Description: Use specified ACME profile
--acme-profile)
shift 1
check_parameters "${1:-}"
PARAM_ACME_PROFILE="${1}"
;;
# PARAM_Usage: --order-timeout seconds
# PARAM_Description: Amount of seconds to wait for processing of order until erroring out
--order-timeout)
shift 1
check_parameters "${1:-}"
PARAM_ORDER_TIMEOUT=${1}
;;
# PARAM_Usage: --validation-timeout seconds
# PARAM_Description: Amount of seconds to wait for processing of domain validations until erroring out
--validation-timeout)
shift 1
check_parameters "${1:-}"
PARAM_VALIDATION_TIMEOUT=${1}
;;
*)
echo "Unknown parameter detected: ${1}" >&2
echo >&2
command_help >&2
exit 1
;;
esac
shift 1
done
case "${COMMAND}" in
env) command_env;;
sign_domains) command_sign_domains;;
register) command_register;;
account) command_account;;
sign_csr) command_sign_csr "${PARAM_CSR}";;
revoke) command_revoke "${PARAM_REVOKECERT}";;
deactivate) command_deactivate;;
cleanup) command_cleanup;;
terms) command_terms;;
cleanupdelete) command_cleanupdelete;;
version) command_version;;
*) command_help; exit 1;;
esac
exit "${exit_with_errorcode}"
}
# Determine OS type
OSTYPE="$(uname)"
if [[ ! "${DEHYDRATED_NOOP:-}" = "NOOP" ]]; then
# Run script
main "${@:-}"
fi
# vi: expandtab sw=2 ts=2

1
root/.gitignore vendored
View file

@ -10,3 +10,4 @@
/.lesshst
/.nano_history
/.profile
/.wget-hsts

7
usr/.gitignore vendored Normal file
View file

@ -0,0 +1,7 @@
/games/
include/
/lib64/
/libexec/
/local/
/share/
/src/

5
usr/bin/.gitignore vendored Normal file
View file

@ -0,0 +1,5 @@
/*
!/.gitignore
!/sendmail
!/mail
!/mailx

1
usr/bin/mail Symbolic link
View file

@ -0,0 +1 @@
s-nail

1
usr/bin/mailx Symbolic link
View file

@ -0,0 +1 @@
s-nail

1
usr/bin/sendmail Symbolic link
View file

@ -0,0 +1 @@
msmtp

3
usr/lib/.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
/*
!/.gitignore
!/sendmail

1
usr/lib/sendmail Symbolic link
View file

@ -0,0 +1 @@
../bin/sendmail

3
usr/sbin/.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
/*
!/.gitignore
!/sendmail

1
usr/sbin/sendmail Symbolic link
View file

@ -0,0 +1 @@
../bin/sendmail

3
var/.gitignore vendored
View file

@ -1,11 +1,8 @@
/.updated
/backups/
/cache/
/local/
/lock
/log/
/mail/
/opt/
/run
/spool/
/www/

16
var/lib/.gitignore vendored
View file

@ -1,27 +1,23 @@
/apache2/
/apt/
/dbus/
/dehydrated/
/dokuwiki/
/dpkg/
/ghostscript/
/git/
/libuuid/
/initscripts/
/logrotate/
/man-db/
/misc/
/pam/
/php/
/private/
/prometheus/
/python/
/samba/
/sgml-base/
/shells.state
/smartmontools/
/snmp/
/sudo/
/systemd/
/terraform-http-backend/
/ucf/
/update-rc.d/
/urandom/
/vim/
/wtmpdb/
/xfonts/
/xml-core/

Some files were not shown because too many files have changed in this diff Show more