Compare commits

...

265 Commits

Author SHA1 Message Date
joeac 87527646fa certbot is --non-interactive 2026-07-07 13:29:26 +01:00
joeac 30af54b750 tls before nginx 2026-07-07 13:26:51 +01:00
joeac ac0ebb5302 add actualbudget 2026-07-07 13:25:30 +01:00
joeac 4bf24c2b18 mox_clientsettings: reverse proxy to mox 2026-07-07 13:06:55 +01:00
joeac 20b396effd adds mox nginx configs 2026-07-07 13:03:08 +01:00
joeac b3677dad4c zen, not sbl, .spamhaus.org 2026-07-07 11:13:32 +01:00
joeac b181f59f4c mkdir ~/mox/data if needed 2026-07-07 11:07:53 +01:00
joeac 5d849384bc chown tls_certs 2026-07-07 10:27:10 +01:00
joeac 5e640711ce fix cert-name in tls.mk 2026-07-07 10:22:32 +01:00
joeac 44e4605be8 adds install_tls rule 2026-07-07 10:11:01 +01:00
joeac 60ba3328fa improves certbot cmds 2026-07-07 10:07:17 +01:00
joeac 5a5301fefb fixes certonly command 2026-07-07 10:06:33 +01:00
joeac 4ee7c34161 mox depends on tls certs 2026-07-07 09:53:24 +01:00
joeac fe1d19a9c7 mox/reinstall 2026-07-07 09:49:24 +01:00
joeac 6d8541f052 install tls_domain, not tls_module 2026-07-07 09:48:09 +01:00
joeac ba2359f8b9 again 2026-07-07 09:41:35 +01:00
joeac 9ef09754be fix renew rule call 2026-07-07 09:37:48 +01:00
joeac cbe223166e certbot delete is non-interactive 2026-07-07 09:35:42 +01:00
joeac fb2785f694 again 2026-07-07 09:34:55 +01:00
joeac f9dcf157a0 fix delete_cert for real this time 2026-07-07 09:33:13 +01:00
joeac 83a482de03 fix syntax in delete_cert rule call 2026-07-07 09:30:11 +01:00
joeac 208f383925 if master node, install all subdomains, else none 2026-07-07 09:28:21 +01:00
joeac 05f9535a9b tls.mk: remove 'test' 2026-07-07 09:23:02 +01:00
joeac c18fd9c44e tls.mk: subdomains, not modules 2026-07-07 09:20:06 +01:00
joeac 07fa302d43 tls.mk 2026-07-07 09:10:58 +01:00
joeac 4a2b27f54a microlog post 2026-07-06 2026-07-06 12:58:25 +01:00
joeac ff507ea16a adds conf to mox deps 2026-07-05 23:23:01 +01:00
joeac 639196f0c9 install mox config 2026-07-05 23:18:11 +01:00
joeac 404cb2d98c also dirs != ordinary files 2026-07-05 23:08:02 +01:00
joeac 665d808660 fix case in last two commits 2026-07-05 23:06:29 +01:00
joeac 15027fef29 ditto, and fix dir 2026-07-05 23:05:18 +01:00
joeac 26ae12f638 calcs gemini_user in make, not shell 2026-07-05 23:04:09 +01:00
joeac 56393380b9 only make .env if dir exists 2026-07-05 23:01:56 +01:00
joeac d51d1a1266 adds mox_clientsettings to blade-canongate 2026-07-05 22:59:42 +01:00
joeac af5599ba54 missed a - 2026-07-05 22:58:57 +01:00
joeac ce8017c6d2 remove ref to removed install_dyndns rule 2026-07-05 22:47:45 +01:00
joeac b64f8ddffa replaces - with _ in vars 2026-07-05 22:30:21 +01:00
joeac e926d562c0 adds mox ports 2026-07-05 22:29:03 +01:00
joeac 064adbc0b7 adds mox sub-subdomains 2026-07-05 22:28:53 +01:00
joeac 4872b95c43 cp, not mv, resolv.conf 2026-07-05 16:30:24 +01:00
joeac 4547dd5681 unbound-anchor requires sudo 2026-07-05 16:27:06 +01:00
joeac 655ac1404a fix /etc/resolv.conf.joeac.net-backup rule 2026-07-05 16:24:12 +01:00
joeac 521d768635 adds mox 2026-07-05 16:09:20 +01:00
joeac f736c46b81 defines openrc rules for all modules (so they can be uninstalled) 2026-07-04 20:13:36 +01:00
joeac f537b99d02 uses IMAGE_PREFIX var in gemini.Dockerfile 2026-07-04 20:12:04 +01:00
joeac ad4b03871e moves container.mk vars to vars.mk so that IMAGE_PREFIX is defined
before it is used in COMPOSE_CMD
2026-07-04 20:11:07 +01:00
joeac 4ef4bbd4ad gives gemini pi-broughton -> blade-canongate 2026-07-04 20:02:02 +01:00
joeac 2e44bfa09a remove nginx site requires sudo 2026-07-04 14:25:49 +01:00
joeac 424b4c6971 uses ip addr instead of hostname to simplify dns config 2026-07-04 14:18:42 +01:00
joeac 4130448a55 swaps master node to blade-canongate 2026-07-04 08:43:00 +01:00
joeac ed6a6e5a34 update.sh exports XDG_RUNTIME_DIR 2026-07-03 16:29:17 +01:00
joeac 36ccd48cfc fix dollars in static.conf.template getting removed 2026-07-03 16:23:01 +01:00
joeac 61f2b376ee chown /var dirs 2026-07-03 16:02:05 +01:00
joeac b59888dc99 splits sudo to avoid env confusion 2026-07-03 15:50:14 +01:00
joeac d29e120c72 ...but for real this time 2026-07-03 15:40:15 +01:00
joeac 16cc43ad28 fix bin/pp again? 2026-07-03 15:37:36 +01:00
joeac 3773af632c fix bin/pp rule 2026-07-03 15:34:19 +01:00
joeac 2aeb58d9ed no quotes around COMPOSECMD 2026-07-03 15:23:13 +01:00
joeac affc7521d6 chmod +x for joeac.net openrc service 2026-07-03 15:21:41 +01:00
joeac f5a7d78d4f uses custom COMPOSECMD in joeac.net openrc services 2026-07-03 15:14:02 +01:00
joeac c42c636231 splits sudo to avoid env confusion 2026-07-03 15:08:46 +01:00
joeac 99b21dbe8e stores src in $HOME and more perm tweaks 2026-07-03 15:01:48 +01:00
joeac 3af4546839 adds XDG_RUNTIME_DIR explicitly in update.sh 2026-07-03 13:38:21 +01:00
joeac ace7801796 typo in openrc.mk: joeac.net.$(module) 2026-07-03 13:23:20 +01:00
joeac 7d0a920c8c provides ETHERPAD_VERSION in vars.mk 2026-07-03 12:37:02 +01:00
joeac f24f1ff4b7 provides ALPINE_VERSION in vars.mk 2026-07-03 12:31:49 +01:00
joeac 703359301b envsubst uses -io flags instead of positional params 2026-07-03 12:29:31 +01:00
joeac 66da50eb92 logins back in after updating groups 2026-07-03 12:27:50 +01:00
joeac 757a24894a chmod 770 on /home/joeac.net 2026-07-03 12:20:24 +01:00
joeac 4b19aabba6 chmod on .env 2026-07-03 12:14:02 +01:00
joeac 626642cd25 get_var_value 2026-07-03 12:12:25 +01:00
joeac a1c91da619 set +e install.sh 2026-07-03 12:07:05 +01:00
joeac fac4169389 removes CONTAINER_PREFIX from example.env (redundant) 2026-07-03 12:06:34 +01:00
joeac a5f1ea1358 copes with empty var values 2026-07-03 12:05:45 +01:00
joeac db8df130fe removes ^ from expr for portability 2026-07-03 12:02:38 +01:00
joeac 52f4ab3157 more portable conditon 2026-07-03 12:00:02 +01:00
joeac 8519d854fb expr has : 2026-07-03 11:51:16 +01:00
joeac edd01e4445 absolutely provides dir to make in install.sh 2026-07-03 11:47:05 +01:00
joeac 9ea2820411 absolutises example.env 2026-07-03 11:46:36 +01:00
joeac 967818f315 absolute chown /home/jeoac.net/joeac.net 2026-07-03 11:45:43 +01:00
joeac ca8e06f300 Merge branch 'main' of https://git.joeac.net/joeac/joeac.net 2026-07-03 11:44:50 +01:00
joeac a611b5010f another attempt to fix perms 2026-07-03 11:44:22 +01:00
joeac 2bc353c8fc install.sh gives rw permissions to user over repo using groups 2026-07-03 11:41:00 +01:00
joeac d4dd979311 install.sh gives rw permissions to user over repo using groups 2026-07-03 11:39:27 +01:00
joeac cd4bafbed3 install.sh: no password for joeac.net user 2026-07-03 11:22:56 +01:00
joeac 51d7222c84 install.sh: adds missing joeac/ in repo URL 2026-07-03 11:21:25 +01:00
joeac 888df5c664 install.sh: replaces doas with sudo 2026-07-03 11:20:36 +01:00
joeac 220394ed0d don't set -x in install.sh 2026-07-03 11:19:26 +01:00
joeac 89280d6087 install.sh: wget to /usr requires doas 2026-07-03 11:19:01 +01:00
joeac cb3ad780b1 install.sh: chmod +x in /usr needs doas 2026-07-03 11:17:46 +01:00
joeac 9615c940bb specifies explicit ENVSUBST_VERSION if wget from github 2026-07-03 11:17:17 +01:00
joeac 33e0fb21d6 set -x in install.sh 2026-07-03 11:15:10 +01:00
joeac 2a8b2b3a40 install.sh specifies latest version of envsubst when installing with go
install
2026-07-03 11:11:43 +01:00
joeac f765e1d38f go get -> go install 2026-07-03 11:06:21 +01:00
joeac e6c011d007 removes extraneous " in install.sh 2026-07-03 11:04:37 +01:00
joeac ba8aaa4ade removes redundant README stuff 2026-07-03 11:04:00 +01:00
joeac 9a93c6f983 install.sh installs dependencies 2026-07-03 11:03:36 +01:00
joeac 803e9e00e0 install.sh picks up where left off with env vars 2026-07-03 10:49:19 +01:00
joeac bb795a9555 install.sh picks up with cloning where left off 2026-07-03 10:46:58 +01:00
joeac ac81aeed31 install.sh doesn't attempt to re-add joeac.net user if already exists 2026-07-03 10:44:52 +01:00
joeac 6a4d6d88c5 install.sh creates remote_smtp_password 2026-07-03 10:41:08 +01:00
joeac 32ae7e2b38 checks for some dependencies in install.sh 2026-07-03 10:35:44 +01:00
joeac 4e62da3d52 installs etherpad data dir 2026-07-03 10:29:34 +01:00
joeac b19ae63ceb Merge branch 'main' of https://git.joeac.net/joeac/joeac.net 2026-07-03 10:28:22 +01:00
joeac 17c7e2446c pulls out GEMINI_CERTIFICATES_DIR and GEMINI_COMITIUM_DATA_DIR 2026-07-03 10:28:13 +01:00
joeac 1dab2c159a uninstalling module openrc file uses -f flag to avoid errors 2026-07-03 10:17:07 +01:00
joeac 9cabb1053d adds missing dollar in uninstall_module 2026-07-03 10:17:07 +01:00
joeac caa2f2d59c adds needed sudo to nginx module uninstall 2026-07-03 10:17:07 +01:00
joeac 6a23042b74 makes capitalise func POSIX-compatible 2026-07-03 10:17:07 +01:00
joeac 33d13bb455 appends /data to VAULTWARDEN_DATA_DIR 2026-07-03 10:13:09 +01:00
joeac 0074ad6643 pulls out ETHERPAD_DATA_DIR 2026-07-03 10:12:49 +01:00
joeac e2d3c05376 make install installs vaultwarden data dir 2026-07-03 10:09:47 +01:00
joeac c62f30ec32 adds missing space in openrc.mk 2026-07-03 10:06:10 +01:00
joeac 536a108040 install.sh sets up .env and DIGITALOCEAN_TOKEN 2026-07-03 09:57:48 +01:00
joeac c1525eaa60 automatically makes user.USER service for initing XDG_RUNTIME_DIR 2026-07-03 09:30:26 +01:00
joeac dcd2e1cd19 adds install.sh to install joeac.net under user joeac.net 2026-07-03 09:18:18 +01:00
joeac 19865adb6a pulls out USER variable 2026-07-03 09:02:22 +01:00
joeac b705e9e1e5 nginx installation uses templates and vars instead of explicit conf for
each module
2026-07-02 23:16:29 +01:00
joeac 87a6a3f1f8 adds PUBLIC_ROOT_DIR_ln to vars.mk 2026-07-02 22:33:50 +01:00
joeac 5914e2e578 removes capitalise from container.mk as now in vars.mk 2026-07-02 22:28:43 +01:00
joeac e39c7a47fc etherpad/settings is templated for port 2026-07-02 22:28:13 +01:00
joeac 24c55e142b PORT_module is aliased to MODULE_PORT 2026-07-02 22:27:50 +01:00
joeac de19519be0 makes module rules for all modules, not just ones to be installed here 2026-07-02 22:24:07 +01:00
joeac 3d87e928d4 make_module uses Makefile, not install.mk 2026-07-02 22:23:55 +01:00
joeac c89f338601 re-orders vars.mk 2026-07-02 17:55:00 +01:00
joeac 6feaddc542 adds some line breaks to vars.mk 2026-07-02 17:52:25 +01:00
joeac eaecbcf41f moves ports from .env to make 2026-07-02 17:51:33 +01:00
joeac 7b07b75747 Revert "sets MASTER_NODE to blade-canongate, not pi-broughton"
This reverts commit 0f397b0ee3.
2026-07-02 17:06:11 +01:00
joeac 0f397b0ee3 sets MASTER_NODE to blade-canongate, not pi-broughton 2026-07-02 17:03:44 +01:00
joeac 69918e681f microlog post: 2026-07-02 2026-07-02 16:21:33 +01:00
joeac cb90b72836 only pushes if is own image 2026-07-02 09:50:13 +01:00
joeac f5a6ffa8de COMPOSE_CMD specifies IMAGE_PREFIX 2026-07-02 09:48:13 +01:00
joeac d3845601e9 gets container_image_name from podman-compose config 2026-07-02 09:44:20 +01:00
joeac 1385472aaf push_module does not require build_module 2026-07-02 09:42:26 +01:00
joeac 5fd15c706b build_module only requires Dockerfile if one exists 2026-07-02 09:41:07 +01:00
joeac 5bd502c72f better crontab with update.sh 2026-07-02 09:39:10 +01:00
joeac f39c4a51dd adds empty build, push rules 2026-07-02 09:35:47 +01:00
joeac 8e857abf29 Merge branch 'main' of https://git.joeac.net/joeac/joeac.net 2026-07-02 09:34:38 +01:00
joeac 2abd95da6d has empty make_module rules 2026-07-02 09:34:38 +01:00
joeac 15a3697679 removes any existing joeac.net openrc service file before installing 2026-07-02 09:26:33 +01:00
joeac a2d7299e72 tidy Makefile 2026-07-02 09:23:33 +01:00
joeac dcdda64b9e distinguishes NGINX_SUBDOMAINS from SUBDOMAINS 2026-07-02 09:19:09 +01:00
joeac 5cc5b04b18 moves subdomain defs to top of vars.mk so can be used for SUBDOMAINS var 2026-07-02 09:17:14 +01:00
joeac 0c87d0cc65 Merge branch 'main' of https://git.joeac.net/joeac/joeac.net 2026-07-02 09:08:02 +01:00
joeac a7ea5780cc prunes dyndns crontabs on reinstall 2026-07-02 09:06:46 +01:00
joeac 6f06fc9503 prunes nginx sites on reinstall 2026-07-02 09:04:02 +01:00
joeac 6bc1f2d05f prunes nginx sites on reinstall 2026-07-02 08:53:24 +01:00
joeac c736041f3c adds uninstall_nginx_module rule content 2026-07-02 08:29:49 +01:00
joeac 8a5ad04776 adds reinstall rule 2026-07-02 08:10:25 +01:00
joeac 6a726a331d simplifies uninstall rule with var 2026-07-02 08:10:13 +01:00
joeac b0fe5b4a44 uses vars to simplify install rule 2026-07-02 08:05:51 +01:00
joeac 0e4aaabb54 all nginx modules are installed on master node 2026-07-01 18:45:42 +01:00
joeac 8ddbae5ee2 fix foreach in BUILD_RULES, PUSH_RULES 2026-07-01 18:40:13 +01:00
joeac cfa0dd5a9a adds reinstall/uninstall nginx module rules 2026-07-01 18:39:20 +01:00
joeac 5644789d64 all rule builds stuff 2026-07-01 18:37:44 +01:00
joeac c7c8a96a57 moves helper makefiles into make/ dir 2026-07-01 18:31:34 +01:00
joeac f73512107c renames some module rules 2026-07-01 18:26:22 +01:00
joeac f8401d00a4 fixes indent in dyndns.mk 2026-07-01 18:22:53 +01:00
joeac b79037c055 only install openrc module if it is an openrc module 2026-07-01 18:20:01 +01:00
joeac 8af9a55187 move uninstall_joeac.net_service to openrc.mk 2026-07-01 18:19:43 +01:00
joeac 1b200f217b move vars to vars.mk 2026-07-01 18:19:26 +01:00
joeac c0e6d13a1f moves stuff to nginx.mk 2026-07-01 18:11:08 +01:00
joeac 2b00e03999 pulls out uninstall to openrc.mk 2026-07-01 17:55:30 +01:00
joeac bf2dabe3f4 pulls out more dyndns stuff to dyndns.mk 2026-07-01 17:49:04 +01:00
joeac d0f549ce22 removes unneeded nginx vars in Makefiles 2026-07-01 17:33:53 +01:00
joeac 89165e9d88 pulls vars out to container.mk 2026-07-01 17:29:16 +01:00
joeac a601e93d00 pulls out nginx_module.mk 2026-07-01 17:22:50 +01:00
joeac fa4d275cc0 pulls out container.mk 2026-07-01 17:11:59 +01:00
joeac 9867d4f232 pulls out openrc.mk 2026-07-01 16:51:44 +01:00
joeac e3b3484905 switches to directory for submake file 2026-07-01 16:47:06 +01:00
joeac def393b930 only restart openrc service if one exists on reinstall 2026-07-01 16:47:06 +01:00
Joe Carstairs c1096e2b01 pulls out nginx.mk 2026-07-01 15:46:05 +01:00
Joe Carstairs 04e1dad952 pulls out crontab.mk 2026-07-01 15:24:01 +01:00
Joe Carstairs e170bafffc pulls out dyndns.mk 2026-07-01 15:21:01 +01:00
Joe Carstairs 23f31a8c4d Makefile installs modules per hostname 2026-07-01 15:10:23 +01:00
joeac d5a5375379 add missing " in ln.joeac.net/milehouse 2026-06-30 17:06:31 +01:00
joeac 7d520d864e Makefile: adds reinstall rule 2026-06-30 16:59:23 +01:00
joeac 16063402be post changes update index in http 2026-06-30 16:41:00 +01:00
joeac 0520592fc5 fix typo: errant ) in Makefile 2026-06-30 16:23:26 +01:00
joeac f27a25fdf5 Merge branch 'main' of https://git.joeac.net/joeac/joeac.net 2026-06-30 16:20:24 +01:00
joeac 0181a703f9 add microlog post 2026-06-30 2026-06-30 16:20:20 +01:00
joeac aad7967402 fix ln.joeac.net/milehouse 2026-06-30 13:47:35 +01:00
joeac 7814c0323e remove empty vaultwarden dir from tracking 2026-06-30 10:16:22 +01:00
joeac eb1ee09769 fixes meta http-equiv tags for redirects 2026-06-30 10:02:28 +01:00
joeac 5265f3e83c uninstall uses sub-install.mk 2026-06-30 09:49:34 +01:00
joeac 5aa03f88dc fixes ln/install.mk 2026-06-30 09:46:17 +01:00
joeac ff2a56ac12 improves yq command 2026-06-30 09:43:50 +01:00
joeac 51ce3374b9 adds ln module 2026-06-30 09:36:12 +01:00
joeac 16576fd1f6 can have a sub-install.mk 2026-06-30 09:35:32 +01:00
joeac 3ff52465dd Makefile doesn't assume that every service has Makefile and Compose
service
2026-06-30 09:35:18 +01:00
joeac 0e9f8e2dd6 silences which complaining if no arch 2026-06-30 08:51:23 +01:00
joeac 4225f3c8da Merge branch 'main' of https://git.joeac.net/joeac/joeac.net 2026-06-30 08:23:19 +01:00
joeac fff8c26df9 more container prefixes in compose.yml 2026-06-29 19:38:17 +01:00
joeac 7d8a986784 adds sane defaults in example.env 2026-06-29 19:29:38 +01:00
joeac 4e25b796ca remove bollocks advice on LOCAL_SMTP_USER 2026-06-29 19:27:30 +01:00
joeac 581c1c0c0a see also LOCAL_SMTP_PORT in example.env 2026-06-29 19:26:46 +01:00
joeac 8d1b6b114a uses env vars in compose.yml 2026-06-29 19:24:48 +01:00
joeac 75ca9d485d adds etherpad module 2026-06-29 12:01:49 +01:00
joeac 74dc86d56c fixes /etc/periodic/daily/joeac.net in Makefile 2026-06-29 12:00:17 +01:00
joeac 3e3c866ec0 uninstalls nginx module confs in Makefile 2026-06-29 11:59:47 +01:00
joeac 2b0c63a783 removes errant ) in Makefile 2026-06-29 11:59:15 +01:00
joeac 8386beac1d installs dyndns in Makefile 2026-06-29 11:59:02 +01:00
joeac dc9694fb32 Makefile: realpath ~ instead of realpath ~/.config/.. which may not exist 2026-06-29 09:29:19 +01:00
joeac 70a155a0a7 Makefile: CPU_ARCH can use arch instead of lscpu to find CPU architecture 2026-06-29 09:28:53 +01:00
joeac 673aaf1c13 installs nginx per module 2026-06-29 09:06:17 +01:00
joeac c059bc34d8 adds pwd.joeac.net.conf to nginx 2026-06-29 07:40:09 +01:00
joeac f2a3552286 abuses container_name in compose.yml 2026-06-29 07:32:35 +01:00
joeac f491fe517a adds vaultwarden module on pwd.joeac.net 2026-06-29 07:32:35 +01:00
joeac f6c8f4fae6 remove redundant uninstall_service rule in Makefile 2026-06-29 07:32:35 +01:00
joeac b43ea19e1e starts joeac.net services on boot 2026-06-29 07:32:35 +01:00
joeac c6ff40e288 moves openrc -> openrc/init.d 2026-06-29 07:32:35 +01:00
joeac 86509e2598 installs joeac.net services as separate OpenRC services 2026-06-29 07:32:35 +01:00
joeac adc5498641 adds nginx config, can make install_nginx 2026-06-29 07:32:29 +01:00
joeac 74d779ee35 adds nginx config, can make install_nginx 2026-06-26 10:40:50 +01:00
joeac cc25a91cf1 adds advisory openrc/user-runlevel-default 2026-06-26 09:45:19 +01:00
joeac 13c909f085 chmod 700 in http.Dockerfile (WTF?) 2026-06-25 19:10:25 +01:00
joeac 2823433f7c Merge branch 'main' of https://git.joeac.net/joeac/joeac.net 2026-06-25 19:04:23 +01:00
joeac abfb28dea2 http.Dockerfile: db dir is owned by nginx and mode 600 2026-06-25 19:04:12 +01:00
joeac ebac73704b rename 2026-06-25.md -> .gmi 2026-06-25 18:57:54 +01:00
joeac 74f1df6893 provides SMTP_PORT, SMTP_USER and SMTP_PASSWORD explicitly in compose.yml ;( 2026-06-25 18:54:13 +01:00
joeac 1ef4c22ec6 apk add php85-pdo, php83-pdo_sqlite in http.Dockerfile 2026-06-25 18:52:59 +01:00
joeac 262516d3da apk add gettext gnutls in smtp.Dockerfile (deps of msmtp) 2026-06-25 18:52:02 +01:00
joeac 1304c5180f Merge branch 'main' of https://git.joeac.net/joeac/joeac.net 2026-06-25 17:52:13 +01:00
joeac c3cabed6e7 db is g+rw in http.Dockerfile 2026-06-25 17:51:59 +01:00
Joe Carstairs 274b79f293 microlog post 2026-06-25 2026-06-25 16:29:45 +01:00
joeac aa76b5ad79 prepares DB_PATH in http.Dockerfile 2026-06-25 12:48:47 +01:00
joeac 84496271c4 adds http/vendor to http image 2026-06-25 12:48:07 +01:00
joeac ac4670492e fixes COPY instructions in gemini.Dockerfile 2026-06-25 11:56:33 +01:00
joeac aaed0c2547 adds gcc (dependency for agate) in gemini/Dockerfile 2026-06-25 11:47:54 +01:00
joeac ed13289934 compose down timeout is 5s, not 300s 2026-06-25 11:45:36 +01:00
joeac a575ecdd68 don't make anything in gemini/run.sh 2026-06-25 11:30:55 +01:00
joeac 0a2a4c68fa rc-update adds joeac.net service to 'default' 2026-06-25 11:29:58 +01:00
joeac d9692da89c replaces 'stop' with 'down' to remove containers (so that they get
re-created with fresh images)
2026-06-25 11:29:12 +01:00
joeac fbbc8d2d8b Revert "adds --rm to podman-compose up command to remove containers after"
This reverts commit 812d59e4dd.
2026-06-25 11:27:33 +01:00
joeac d27186a177 copies gemini/run.sh into image 2026-06-25 11:26:22 +01:00
joeac 812d59e4dd adds --rm to podman-compose up command to remove containers after
stopped
2026-06-25 11:25:10 +01:00
joeac 995c258aa5 adds install, uninstall rules to Makefile 2026-06-25 11:17:01 +01:00
joeac bd9af70a97 removes dependencies from openrc/joeac.net 2026-06-25 11:17:01 +01:00
joeac 465c40b927 removes extra command make from openrc/joeac.net 2026-06-25 11:17:01 +01:00
joeac 6f11b8c453 removes redundant JOEACNET_USER var from openrc/joeac.net 2026-06-25 11:17:01 +01:00
joeac 86ec9e9d54 uses rootless podman in Makefile 2026-06-25 11:17:01 +01:00
joeac 78fe3e7956 bin/pp is executable and a dependency of out rule in http/Makefile 2026-06-25 11:17:01 +01:00
joeac ad8a8c3cac openrc/joeac.net 2026-06-25 11:17:01 +01:00
joeac 46596fc5f6 maps env vars for msmtp image in smtp.Dockerfile 2026-06-25 11:15:54 +01:00
joeac f09bbf8d4a replaces prune_blog script with http/Makefile rules 2026-06-25 09:49:14 +01:00
joeac 83e0f1cda5 http: replaces prune_out script with make rules 2026-06-25 08:22:27 +01:00
joeac aa4f63a8ce uses grep short flags for POSIX compatibility 2026-06-24 22:43:32 +01:00
joeac 499a10837f minor changes to composer.lock 2026-06-24 22:12:49 +01:00
joeac 405ccd1709 adds composer install to http/Makefile 2026-06-23 09:00:49 +01:00
joeac b735c95c84 php-fpm gets env vars 2026-06-23 08:43:40 +01:00
joeac e61a0f1de9 php-fpm logs errors 2026-06-23 08:43:35 +01:00
joeac 52b013e165 fastcgi SCRIPT_FILENAME looks in /usr/share/nginx/html 2026-06-23 08:27:52 +01:00
joeac 76081fd88f adds =404 to end of try_files directive 2026-06-23 08:18:46 +01:00
joeac 4a9649f096 adds ; in fastcgi_pass directive in http/nginx.conf 2026-06-23 08:14:40 +01:00
joeac 061b6986a3 php-fpm.conf lives in /etc/php85/fpm/pool.d in http image 2026-06-23 07:58:32 +01:00
joeac ff49052baa php-fpm runs on socket in /run 2026-06-23 07:57:33 +01:00
joeac 7bd5255c63 http.Dockerfile: runs php-fpm and nginx 2026-06-23 00:06:54 +01:00
joeac 473f4b19f0 nginx.conf: moves server into http block 2026-06-23 00:06:44 +01:00
joeac e04d1e55a1 adds nginx/php-fpm config 2026-06-22 23:45:46 +01:00
joeac e23f053b89 http ports: 8080:80, not 8080:8080 2026-06-22 22:59:37 +01:00
joeac ddc416a45a Makefile: build_$(module) depends on $(module).Dockerfile 2026-06-22 22:56:20 +01:00
joeac c07f55e8d4 move smtp/Dockerfile to smtp.Dockerfile 2026-06-22 22:55:34 +01:00
joeac d3e832f064 http/Dockerfile: COPY to nginx folder 2026-06-22 22:53:53 +01:00
joeac 6e5c1c158c gemini/Makefile: FEED_TARGET includes comitium.json, not
subscriptions.json
2026-06-22 22:47:14 +01:00
joeac 07a326114e cleans $(FEED_TARGET) before rebuildings comitium feeds in
gemini/Makefile
2026-06-22 22:46:18 +01:00
56 changed files with 1663 additions and 216 deletions
+3
View File
@@ -5,3 +5,6 @@ indent_size = 2
[*.{md,markdown,mdx}] [*.{md,markdown,mdx}]
max_line_length = 80 max_line_length = 80
[{Makefile,*.mk}]
indent_style = tab
+1
View File
@@ -26,3 +26,4 @@ pnpm-debug.log*
**/*.tfstate.backup **/*.tfstate.backup
*.sqlite *.sqlite
DIGITALOCEAN_TOKEN
+47 -40
View File
@@ -1,36 +1,13 @@
############# include make/vars.mk
# VARIABLES #
#############
CPU_ARCH := $(shell lscpu | grep ^Architecture: | sed "s/^Architecture:[[:space:]]*\([[:alnum:][:punct:]]\+\).*/\1/") submake_file = $(shell [ -f "$(module)/Makefile" ] && echo "$(module)/Makefile")
IMAGE_PREFIX := $(if $(filter armv7%,$(CPU_ARCH)),armv7/) install_submake_file = $(shell [ -f "$(module)/install.mk" ] && echo "$(module)/install.mk")
REGISTRY_DOMAIN := git.joeac.net
REGISTRY_USER := joeac
MODULES := http gemini smtp
#############
# FUNCTIONS #
#############
container_image_name = $(REGISTRY_DOMAIN)/$(REGISTRY_USER)/joeac.net-$(module)
define build_module_rule =
.PHONY: build_$(module)
build_$(module): make_$(module)
sudo podman-compose build $(module)
endef
define push_module_rule =
.PHONY: push_$(module)
push_$(module): login_registry build_$(module)
sudo podman push $(container_image_name)
endef
define make_module_rule = define make_module_rule =
.PHONY: make_$(module) .PHONY: make_$(module)
make_$(module): $(module)/.env make_$(module): $(module)/.env
$(MAKE) --directory=$(module) $(if $(submake_file),\
$(MAKE) --makefile=$(notdir $(submake_file)) --directory=$(module))
endef endef
define module_env_rule = define module_env_rule =
@@ -38,22 +15,52 @@ $(module)/.env: .env
cp .env $(module)/.env cp .env $(module)/.env
endef endef
define install_module_rule =
.PHONY: install_$(module)
install_$(module): install_openrc_$(module) install_dyndns_$(module) $(if $(SUBDOMAIN_$(module)),install_tls_$(SUBDOMAIN_$(module))) $(install_submake_file)
$(if $(install_submake_file),$(MAKE) --makefile=$(notdir $(install_submake_file)) --directory=$(dir $(install_submake_file)) install)
endef
######### define reinstall_module_rule =
# RULES # .PHONY: reinstall_$(module)
######### reinstall_$(module): reinstall_openrc_$(module) reinstall_dyndns_$(module) $(if $(SUBDOMAIN_$(module)),reinstall_tls_$(SUBDOMAIN_$(module))) $(install_submake_file)
$(if $(install_submake_file),$(MAKE) --makefile=$(notdir $(install_submake_file)) --directory=$(dir $(install_submake_file)) reinstall)
endef
all: $(foreach module,$(MODULES),push_$(module)) define uninstall_module_rule =
.PHONY: uninstall_$(module)
uninstall_$(module): uninstall_openrc_$(module) uninstall_dyndns_$(module) $(if $(SUBDOMAIN_$(module)),install_tls_$(SUBDOMAIN_$(module)))
$(if $(install_submake_file),\
$(MAKE) --makefile=$(notdir $(install_submake_file)) --directory $(dir $(install_submake_file)) uninstall
)
endef
$(foreach module,$(MODULES),$(eval $(call build_module_rule))) .PHONY: all
$(foreach module,$(MODULES),$(eval $(call push_module_rule))) all: $(ENV_RULES) $(MAKE_RULES) $(BUILD_RULES) $(PUSH_RULES)
$(foreach module,$(MODULES),$(eval $(call make_module_rule)))
$(foreach module,$(MODULES),$(eval $(call module_env_rule)))
.PHONY: login_registry $(foreach module,$(ALL_MODULES),$(eval $(call make_module_rule)))
login_registry: $(foreach module,$(ALL_MODULES),$(eval $(call module_env_rule)))
sudo podman login $(REGISTRY_DOMAIN)
.PHONY: install
install: install_tls install_nginx $(ENV_RULES) $(INSTALL_RULES) install_crontab
.PHONY: reinstall
reinstall: reinstall_tls reinstall_nginx reinstall_dyndns $(ENV_RULES) $(REINSTALL_RULES) reinstall_crontab
.PHONY: uninstall
uninstall: uninstall_nginx uninstall_dyndns uninstall_tls uninstall_joeac.net_service $(UNINSTALL_RULES) uninstall_crontab
$(foreach module,$(ALL_MODULES),$(eval $(install_module_rule)))
$(foreach module,$(ALL_MODULES),$(eval $(reinstall_module_rule)))
$(foreach module,$(ALL_MODULES),$(eval $(uninstall_module_rule)))
.PHONY: clean .PHONY: clean
clean: clean:
$(foreach module,$(MODULES),$(MAKE) --directory=$(module) clean;) $(foreach module,$(MAKE_MODULES),$(MAKE) --directory=$(module) clean;)
include make/container.mk
include make/openrc.mk
include make/nginx.mk
include make/crontab.mk
include make/dyndns.mk
include make/tls.mk
+86 -27
View File
@@ -2,44 +2,103 @@
Joe Carstairs' public Internet presence Joe Carstairs' public Internet presence
Structure: To install:
``` ```sh
/ wget -O- https://git.joeac.net/joeac/joeac.net/raw/branch/main/install.sh | sh
├── gemini My Gemini capsule
├── smtp A local SMTP server
└── http My Website
``` ```
## Running with Podman ## DNS setup
These instructions will probably work with Docker, too: just substitute `podman` A/AAAA DNS records are added automatically by `make install`, but in order to
for `docker` in all the commands. get `mox` working as an email server, you'll have to manually add the following
DNS records.
To run with Podman, first set up your environment variables. Copy `example.env` Deliver mail for mail.joeac.net to mail.joeac.net:
to `.env` and edit the values accordingly.
Then, create the `remote_smtp_password` secret, storing the password for the ```
remote SMTP server which will send the contact emails on behalf of the website. mail.joeac.net. MX 10 mail.joeac.net.
```bash
sudo podman secret create remote_smtp_password /path/to/remote/smtp/password
``` ```
Now build and start the containers: All emails from the email server will be signed with two DKIM keys. So that
clients can verify the authenticity of the messages, provide these keys as TXT
records:
```bash ```
sudo podman-compose build && sudo podman-compose up -d 2026a._domainkey.mail.joeac.net. TXT v=DKIM1;h=sha256;p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvYfjrzmYgBtYofzBwI80aiW98+M2g6z+gd1Iwz9g0y30rPFNTctFn9GwBNuYBgZiZxB+sqjEbPMbr3li/R7i0A9t/KbNNJhkNC+4IjKJjk+jw1CXm4vXOUa4YSYWwy7NVYTH/QwZGz6fwjVM7YvDnnE4gG2NwrVx+AXlONt2R1G+qgV6HAIIvVi8T0yCjjqEc5B5bKlqk0XU9vSyUFJhhKnR/KNRe79C+H9GWJzcU7HUCmIHX04Xi0JeB/wm3weF1xjtGTsWyy5BmHHsfWGqSr2Dbg5o6AI5W0h4VkQ4QzdEYGVQ9ZBDyqFQwQFXLn0oHZjCD/vFzPOPdM5pxF/OgwIDAQAB
2026b._domainkey.mail.joeac.net. TXT v=DKIM1;h=sha256;p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzcrk9FUt6AdrvnAP3KawuOTLw7uL5SJ+ZYmShuz41zwM6bPQteGSSwddFXIxcqVlJrdFahrK4KvHX/sw/hWVfZoPLDdwsGN5eI8cqQjNDE+JDu9BbPlTituva4Hkve0hbAKDqA8jmbcZg6aU7b44Kzq8UpWAlPO273Rq2tsbCBcITt8B3NFoeY9CSsZU1LqGl855GUtaNyhlPaAvfab3Q9/4wyusPhCHlBYaRK+ZzuSMs5KEOG6n4kbZfMVi2+4c/bPU5PdTuyvbSIEqjNH4TpfatE0I9ubGv0WbAzr5EZbv5+xtukZ/dIisPPMjn1AbjpSJYNYr2OYgey6+WvzRmQIDAQAB
``` ```
## Running on the host machine Specify the MX host is allowed to send for our domain and for itself (for DSNs).
~all means softfail for anything else, which is done instead of -all to prevent
older mail servers from rejecting the message because they never get to looking
for a dkim/dmarc pass.
To run on the host machine, first, as before, set up your environment variables ```
by copying `example.env` to `.env` and editing the values as appropriate. mail.joeac.net. TXT v=spf1 ip4:217.155.190.42 ip6:fdc9:6aec:7a18:0:2e0:4cff:fe61:9b17 mx ~all
```bash
npm run start
``` ```
Note that emails may not work locally without further setup. These instructions Emails that fail the DMARC check (without aligned DKIM and without aligned SPF)
are of course woefully incomplete. should be rejected, and request reports. If you email through mailing lists that
strip DKIM-Signature headers and don't rewrite the From header, you may want to
set the policy to p=none.
```
_dmarc.mail.joeac.net. TXT v=DMARC1;p=reject;rua=mailto:dmarcreports@mail.joeac.net!10m
```
Remote servers can use MTA-STS to verify our TLS certificate with the WebPKI
pool of CA's (certificate authorities) when delivering over SMTP with
STARTTLSTLS.
```
mta-sts.mail.joeac.net. CNAME mail.joeac.net.
_mta-sts.mail.joeac.net. TXT v=STSv1; id=20260705T153220
```
Request reporting about TLS failures.
```
_smtp._tls.mail.joeac.net. TXT v=TLSRPTv1; rua=mailto:tlsreports@mail.joeac.net
```
Client settings will reference a subdomain of the hosted domain, making it
easier to migrate to a different server in the future by not requiring settings
in all clients to be updated.
```
clientsettings.mail.joeac.net. CNAME mail.joeac.net.
```
Autoconfig is used by Thunderbird. Autodiscover is (in theory) used by
Microsoft.
```
autoconfig.mail.joeac.net. CNAME mail.joeac.net.
_autodiscover._tcp.mail.joeac.net. SRV 0 1 443 mail.joeac.net.
```
For secure IMAP and submission autoconfig, point to mail host.
```
_imaps._tcp.mail.joeac.net. SRV 0 1 993 mail.joeac.net.
_submissions._tcp.mail.joeac.net. SRV 0 1 465 mail.joeac.net.
```
Next records specify POP3 and non-TLS ports are not to be used. These are
optional and safe to leave out (e.g. if you have to click a lot in a DNS admin
web interface).
```
_imap._tcp.mail.joeac.net. SRV 0 0 0 .
_submission._tcp.mail.joeac.net. SRV 0 0 0 .
_pop3._tcp.mail.joeac.net. SRV 0 0 0 .
_pop3s._tcp.mail.joeac.net. SRV 0 0 0 .
```
Optional: You could mark Let's Encrypt as the only Certificate Authority allowed
to sign TLS certificates for your domain.
```
mail.joeac.net. CAA 0 issue "letsencrypt.org"
```
+7
View File
@@ -0,0 +1,7 @@
I looked through some concordances while I was bored in the New College Library the other day.
I really love Robert Young's Analytical Concordance. Young's is a concordance to the Authorised Version, so the entries are the English words used in the AV. But each English-language entry groups together all the words in the Greek New Testament and Hebrew Old Testament which correspond to that English word, and lists all the occurrences of each of those words in their respective source texts. That makes it a perfect tool for understanding the relationships between the biblical source texts. The only disadvantage is that it doesn't seem at all interested in the Septuagint, which is really important for understanding the way New Testament authors use the Old Testament.
It astonished me that there are concordances available of the NIV and ESV texts. Why would you want that? The texts don't correspond very well to the Greek or Hebrew source texts, and they don't have nearly as much clout as self-standing faith texts as the Authorised Version does. I really don't get it. If I had one, I would probably never open it.
I couldn't get ahold of a Strong's, but I did happen to drop in Armchair Books on the way back from the library, and they have a beautiful 19th-century Cruden's Concordance. Cruden's was the first English-language concordance when its eponymous author painstakingly constructed it in 1737, and has never been out of print since then. By the looks of it, it remains very relevant for English-speaking readers of the Bible. And going for a bargain as well... if you get there before me, I'll eat your head.
+7
View File
@@ -0,0 +1,7 @@
So I've now got half a dozen services running on my homelab across two machines. I need to install the services on each machine, keep them running after crashes and reboots, update and restart them when the source code changes, and co-ordinate them with each other (since I can only have one public IP on my home network, but I want to serve stuff over the Internet from both machines).
I am currently managing this with Podman, some Dockerfiles and Docker-Compose files, Makefiles, and a lot of manual interference. This just about works, and is probably reasonably sensible for the small, low-consequence situation.
Still, it is a faff. I'm wondering: is this kind of what Kubernetes is for? I've never understood. Looking at the documentation, I find it really hard to understand what Kubernetes is for. Maybe it's for situations kind of like this (only typically much bigger)?
Answers on a postcard please.
+11
View File
@@ -0,0 +1,11 @@
Writing is hard! I've just spent 2 days fixing 1 paragraph in my dissertation. The problem was to give the reader good reason to think that the fossil fuel industry exerts a strong influence on the majority epistemology. The end result is a single paragraph with four citations. You'd think that would take half a day, not 2 full days.
I think what made it hard was that I needed to gain understanding. If I just needed a fact or two, it would have been easier: skim a few abstracts, extract a few figures, call it a day. But I didn't know in advance what fossil-think looks like. I couldn't write a paragraph that was almost done but for a few missing statistics. I needed to know the whens, the hows, the whos.
What I ended up doing was collecting a score of browser tabs with relevant articles and ebooks (which was easy enough), then going through each one and reading it: properly reading it, for understanding, not just skimming abstracts.
This worked: after about half a dozen articles, I reviewed my notes, realised I had enough to be getting on with, and wrote up my paragraph. Along the way I gained a (very shallow) understanding of how the fossil fuel industry influences public discourse.
But: it took a heck of a long time for one paragraph.
I really wish I had an experienced researcher looking over my shoulder, popping by a couple of times a day, to offer advice. Maybe they would tell me: sorry, that's just how it is, you need to gain understanding and that takes time. Or maybe they would say: you should really be cutting the corner here, let me show you how. It's one of the many things you cannot get from a monthly check-in with a supervisor.
+3
View File
@@ -0,0 +1,3 @@
I've been following Ink and Switch's blog for a while. They're working creatively with computers. This is a great discussion about LLMs which covers what they are, how they are being abused to de-humanise the world, and how things could be different, concluding in a call for 'punk computing.' Let's have it!
=> https://www.inkandswitch.com/tangents/artificial/ Artificial | Ink and Switch
+71 -13
View File
@@ -1,37 +1,95 @@
services: services:
actualbudget:
image: docker.io/actualbudget/actual-server:latest-alpine
container_name: joeac.net-actualbudget
restart: unless-stopped
volumes:
- ${ACTUALBUDGET_DATA_DIR}:/data/
ports:
- "${ACTUALBUDGET_PORT}:5006"
gemini: gemini:
image: git.joeac.net/joeac/joeac.net-gemini image: git.joeac.net/joeac/${IMAGE_PREFIX}joeac.net-gemini
container_name: joeac.net-gemini
build: build:
context: . context: .
dockerfile: gemini.Dockerfile dockerfile: gemini.Dockerfile
ports: ports:
- "1965:1965" - "${GEMINI_PORT}:1965"
volumes:
- ${GEMINI_CERTIFICATES_DIR}:/var/app/.certificates
- ${GEMINI_COMITIUM_DATA_DIR}:/var/app/comitium-data
http: http:
image: git.joeac.net/joeac/joeac.net-http image: git.joeac.net/joeac/${IMAGE_PREFIX}joeac.net-http
container_name: joeac.net-http
build: build:
context: . context: .
dockerfile: http.Dockerfile dockerfile: http.Dockerfile
env_file: environment:
- .env MAX_DAILY_EMAILS: ${MAX_DAILY_EMAILS}
CONTACT_MAILBOX: ${CONTACT_MAILBOX}
CONTACT_MAILBOX_NAME: ${CONTACT_MAILBOX_NAME}
LOCAL_SMTP_FROM: ${LOCAL_SMTP_FROM}
LOCAL_SMTP_FROM_NAME: ${LOCAL_SMTP_FROM_NAME}
LOCAL_SMTP_HOST: ${LOCAL_SMTP_HOST}
LOCAL_SMTP_PORT: ${LOCAL_SMTP_PORT}
LOCAL_SMTP_USER: ${LOCAL_SMTP_USER}
LOCAL_SMTP_PASSWORD: ${LOCAL_SMTP_PASSWORD}
DB_SCHEME: ${DB_SCHEME}
DB_PATH: ${DB_PATH}
ports: ports:
- "8080:8080" - "${HTTP_PORT}:80"
etherpad:
image: git.joeac.net/joeac/${IMAGE_PREFIX}joeac.net-etherpad
container_name: joeac.net-etherpad
build:
context: .
dockerfile: etherpad.Dockerfile
args:
ALPINE_VERSION: ${ALPINE_VERSION}
ETHERPAD_VERSION: ${ETHERPAD_VERSION}
volumes:
- ${ETHERPAD_DATA_DIR}:/var/app/var
environment:
NODE_ENV: ${ETHERPAD_NODE_ENV}
ADMIN_PASSWORD: ${ETHERPAD_ADMIN_PASSWORD}
restart: unless-stopped
ports:
- "${ETHERPAD_PORT}:9001"
smtp: smtp:
image: git.joeac.net/joeac/joeac.net-smtp image: git.joeac.net/joeac/${IMAGE_PREFIX}joeac.net-smtp
container_name: joeac.net-smtp
build: build:
context: smtp context: .
dockerfile: smtp.Dockerfile
args: args:
LOCAL_SMTP_PORT: 2500 SMTP_PORT: ${LOCAL_SMTP_PORT}
env_file:
- .env
environment: environment:
LOCAL_SMTP_PORT: 2500 LOCAL_SMTP_ENVELOPE_FROM: ${LOCAL_SMTP_ENVELOPE_FROM}
LOCAL_SMTP_PASSWORD: smtp REMOTE_SMTP_HOST: ${REMOTE_SMTP_HOST}
REMOTE_SMTP_PORT: ${REMOTE_SMTP_PORT}
REMOTE_SMTP_USER: ${REMOTE_SMTP_USER}
SMTP_PORT: ${LOCAL_SMTP_PORT}
SMTP_USER: ${LOCAL_SMTP_USER}
SMTP_PASSWORD: ${LOCAL_SMTP_PASSWORD}
REMOTE_SMTP_PASSWORD_FILE: /run/secrets/remote_smtp_password REMOTE_SMTP_PASSWORD_FILE: /run/secrets/remote_smtp_password
secrets: secrets:
- remote_smtp_password - remote_smtp_password
vaultwarden:
image: docker.io/vaultwarden/server:latest
container_name: joeac.net-vaultwarden
restart: unless-stopped
environment:
DOMAIN: "https://pwd.joeac.net"
volumes:
- ${VAULTWARDEN_DATA_DIR}:/data/
ports:
- "${VAULTWARDEN_PORT}:80"
secrets: secrets:
remote_smtp_password: remote_smtp_password:
external: true external: true
+11
View File
@@ -0,0 +1,11 @@
ARG ALPINE_VERSION=3.23
FROM docker.io/alpine:${ALPINE_VERSION}
RUN mkdir -p /var/app
WORKDIR /var/app
ARG ETHERPAD_VERSION
RUN apk --no-cache add pnpm \
&& ENV=~/.profile SHELL=sh pnpm setup \
&& source ~/.profile \
&& pnpm install --global tsx
COPY etherpad/etherpad-${ETHERPAD_VERSION} .
CMD pnpx tsx src/node/server.ts
+2
View File
@@ -0,0 +1,2 @@
var
etherpad-*
+27
View File
@@ -0,0 +1,27 @@
ETHERPAD_VERSION := 3.3.2
SRC_DIR := etherpad-$(ETHERPAD_VERSION)
.PHONY: all
all: download_etherpad install_deps
.PHONY: download_etherpad
download_etherpad: $(SRC_DIR)
$(SRC_DIR):
wget -O- https://github.com/ether/etherpad/archive/refs/tags/v3.3.2.tar.gz | tar -xz
.PHONY: install_deps
install_deps: $(SRC_DIR)/node_modules
$(SRC_DIR)/node_modules: $(SRC_DIR) $(SRC_DIR)/settings.json $(SRC_DIR)/package.json $(SRC_DIR)/pnpm-lock.yaml
cd $(SRC_DIR) && pnpm install
$(SRC_DIR)/settings.json: $(SRC_DIR) settings.json.template
ifdef ETHERPAD_PORT
ETHERPAD_PORT=$(ETHERPAD_PORT) envsubst -no-unset -i settings.json.template -o $(SRC_DIR)/settings.json
else
$(error ETHERPAD_PORT is not defined)
endif
clean:
rm -rf etherpad-*/
+13
View File
@@ -0,0 +1,13 @@
.PHONY: install
install: $(ETHERPAD_DATA_DIR)
.PHONY: reinstall
reinstall: $(ETHERPAD_DATA_DIR)
$(ETHERPAD_DATA_DIR):
sudo mkdir -p $(ETHERPAD_DATA_DIR)
ETHERPAD_USER=$(whoami) && sudo chown $$ETHERPAD_USER:$$ETHERPAD_USER $(ETHERPAD_DATA_DIR)
.PHONY: uninstall
uninstall:
$(info Nothing to do)
+134
View File
@@ -0,0 +1,134 @@
{
"title": "joeac's docs",
"showRecentPads": true,
"favicon": null,
"skinName": "colibris",
"skinVariants": "super-light-toolbar super-light-editor light-background",
"ip": "0.0.0.0",
"port": ${ETHERPAD_PORT},
"showSettingsInAdminPage": true,
"enableMetrics": "$${ENABLE_METRICS:true}",
"cleanup": {
"enabled": false,
"keepRevisions": 5
},
"dbType": "sqlite",
"dbSettings": {
"filename": "var/etherpad.sq3"
},
"defaultPadText" : "",
"padOptions": {
"noColors": false,
"showControls": true,
"showChat": true,
"showLineNumbers": true,
"useMonospaceFont": false,
"userName": null,
"userColor": null,
"rtl": false,
"alwaysShowChat": false,
"chatAndUsers": false,
"lang": null
},
"padShortcutEnabled" : {
"altF9": true,
"altC": true,
"cmdShift2": true,
"delete": true,
"return": true,
"esc": true,
"cmdS": true,
"tab": true,
"cmdZ": true,
"cmdY": true,
"cmdI": true,
"cmdB": true,
"cmdU": true,
"cmd5": true,
"cmdShiftL": true,
"cmdShiftN": true,
"cmdShift1": true,
"cmdShiftC": true,
"cmdH": true,
"ctrlHome": true,
"pageUp": true,
"pageDown": true
},
"updateServer": "https://etherpad.org/ep_infos",
"suppressErrorsInPadText": false,
"requireSession": false,
"editOnly": false,
"minify": true,
"maxAge": 21600,
"soffice": null,
"docxExport": true,
"allowUnknownFileEnds": true,
"requireAuthentication": false,
"requireAuthorization": false,
"trustProxy": false,
"cookie": {
"keyRotationInterval": 86400000,
"sameSite": "Lax",
"sessionLifetime": 864000000,
"sessionRefreshInterval": 86400000,
"sessionCleanup": true
},
"disableIPlogging": false,
"automaticReconnectionTimeout": 0,
"scrollWhenFocusLineIsOutOfViewport": {
"percentage": {
"editionAboveViewport": 0,
"editionBelowViewport": 0
},
"duration": 0,
"scrollWhenCaretIsInTheLastLineOfViewport": false,
"percentageToScrollWhenUserPressesArrowUp": 0
},
"users": {
"admin": {
"password": "admin",
"is_admin": true
}
},
"socketTransportProtocols" : ["websocket", "polling"],
"socketIo": {
"maxHttpBufferSize": 1000000
},
"loadTest": false,
"dumpOnUncleanExit": false,
"importExportRateLimiting": {
"windowMs": 90000,
"max": 10
},
"importMaxFileSize": 52428800, // 50 * 1024 * 1024
"authenticationMethod": "$${AUTHENTICATION_METHOD:sso}",
"enableDarkMode": "$${ENABLE_DARK_MODE:true}",
"enablePadWideSettings": "$${ENABLE_PAD_WIDE_SETTINGS:false}",
"commitRateLimiting": {
"duration": 1,
"points": 10
},
"logLayoutType": "colored",
"customLocaleStrings": {},
"enableAdminUITests": false,
"lowerCasePadIds": false,
"sso": {
"issuer": "$${SSO_ISSUER:http://localhost:${ETHERPAD_PORT}}",
"clients": [
{
"client_id": "$${ADMIN_CLIENT:admin_client}",
"client_secret": "$${ADMIN_SECRET:admin}",
"grant_types": ["authorization_code"],
"response_types": ["code"],
"redirect_uris": ["$${ADMIN_REDIRECT:http://localhost:${ETHERPAD_PORT}/admin/}"]
},
{
"client_id": "$${USER_CLIENT:user_client}",
"client_secret": "$${USER_SECRET:user}",
"grant_types": ["authorization_code"],
"response_types": ["code"],
"redirect_uris": ["$${USER_REDIRECT:http://localhost:${ETHERPAD_PORT}/}"]
}
]
}
}
+11 -9
View File
@@ -1,15 +1,11 @@
# The hostname to use for the local SMTP server # The hostname to use for the local SMTP server
LOCAL_SMTP_HOST= LOCAL_SMTP_HOST=smtp
# The port to use for the local SMTP server
LOCAL_SMTP_PORT=
# The username for authenticating to the local SMTP server # The username for authenticating to the local SMTP server
# Recommended to be the same as REMOTE_SMTP_USER, else the remote may reject it LOCAL_SMTP_USER=smtp
LOCAL_SMTP_USER=
# The password for authenticating to the local SMTP server # The password for authenticating to the local SMTP server
LOCAL_SMTP_PASSWORD= LOCAL_SMTP_PASSWORD=smtp
# The envelope-from used by the local SMTP server # The envelope-from used by the local SMTP server
# Theoretically should be "LOCAL_SMTP_FROM_NAME <LOCAL_SMTP_FROM>", but in # Theoretically should be "LOCAL_SMTP_FROM_NAME <LOCAL_SMTP_FROM>", but in
@@ -44,7 +40,13 @@ CONTACT_MAILBOX_NAME=
MAX_DAILY_EMAILS= MAX_DAILY_EMAILS=
# The scheme part of the URI to the website database # The scheme part of the URI to the website database
DB_SCHEME= DB_SCHEME=sqlite
# The path part of the URI to the website database # The path part of the URI to the website database
DB_PATH= DB_PATH=/var/app/joeac.net-http.sqlite
# The Node.JS environment for the Etherpad instance (production, development)
ETHERPAD_NODE_ENV=production
# The admin password for the Etherpad instance
ETHERPAD_ADMIN_PASSWORD=
+6 -5
View File
@@ -1,18 +1,19 @@
FROM git.joeac.net/joeac/armv7/agate:3.3.20-alpine3.23 AS agate FROM git.joeac.net/joeac/${IMAGE_PREFIX}agate:3.3.20-alpine3.23 AS agate
FROM git.joeac.net/joeac/armv7/comitium:1.8.2-alpine3.23 AS comitium FROM git.joeac.net/joeac/${IMAGE_PREFIX}comitium:1.8.2-alpine3.23 AS comitium
FROM git.joeac.net/joeac/armv7/crond:1.37.0-r30-alpine3.23 AS final FROM git.joeac.net/joeac/${IMAGE_PREFIX}crond:1.37.0-r30-alpine3.23 AS final
RUN apk --no-cache add gcc # dependency for agate
COPY --from=agate /root/.cargo/bin/agate /usr/local/bin/agate COPY --from=agate /root/.cargo/bin/agate /usr/local/bin/agate
COPY --from=comitium /usr/local/bin/comitium /usr/local/bin/comitium COPY --from=comitium /usr/local/bin/comitium /usr/local/bin/comitium
RUN mkdir -p /var/app/content RUN mkdir -p /var/app/content
WORKDIR /var/app WORKDIR /var/app
COPY gemini/.certificates .certificates
RUN crontab -l > crontab.tmp \ RUN crontab -l > crontab.tmp \
&& echo "0 */6 * * * /usr/local/bin/comitium refresh --data /var/app/comitium-data" >> crontab.tmp \ && echo "0 */6 * * * /usr/local/bin/comitium refresh --data /var/app/comitium-data" >> crontab.tmp \
&& crontab crontab.tmp \ && crontab crontab.tmp \
&& rm crontab.tmp && rm crontab.tmp
COPY gemini/content gemini/comitium-data /var/app/ COPY gemini/run.sh /var/app/
COPY gemini/content /var/app/content
COPY common /var/common COPY common /var/common
CMD ./run.sh CMD ./run.sh
+3 -3
View File
@@ -6,8 +6,8 @@ LOGLOG_HEADER := $(TEMPLATES_DIR)/loglog-header.gmi
MICROLOG_ENTRIES := $(wildcard microlog/*) MICROLOG_ENTRIES := $(wildcard microlog/*)
LONGLOG_ENTRIES := $(wildcard content/logs/longlog/*) LONGLOG_ENTRIES := $(wildcard content/logs/longlog/*)
LOGLOG_TARGET := content/logs/loglog.gmi LOGLOG_TARGET := content/logs/loglog.gmi
FEED_TARGET := $(COMITIUM_DATA)/subscriptions.json $(COMITIUM_DATA)/feed.gmi $(COMITIUM_DATA)/subscriptions.gmi FEED_TARGET := $(COMITIUM_DATA)/comitium.json $(COMITIUM_DATA)/feed.gmi $(COMITIUM_DATA)/subscriptions.gmi
FEED_OUTPUTS := $(FEED_TARGET) $(COMITIUM_DATA)/subscriptions.json $(COMITIUM_DATA)/feed.gmi $(COMITIUM_DATA)/subscriptions.gmi FEED_OUTPUTS := $(FEED_TARGET) $(COMITIUM_DATA)/comitium.json $(COMITIUM_DATA)/feed.gmi $(COMITIUM_DATA)/subscriptions.gmi
MICROLOG_TARGET := content/logs/microlog.gmi MICROLOG_TARGET := content/logs/microlog.gmi
MICROLOG_OUTPUTS := $(MICROLOG_TARGET) $(wildcard content/logs/microlog/*) MICROLOG_OUTPUTS := $(MICROLOG_TARGET) $(wildcard content/logs/microlog/*)
LONGLOG_TARGET := content/logs/longlog.gmi LONGLOG_TARGET := content/logs/longlog.gmi
@@ -25,7 +25,7 @@ $(LOGLOG_TARGET): $(MICROLOG_TARGET) $(LONGLOG_TARGET) $(LOGLOG_HEADER)
bash ./build_loglog.bash bash ./build_loglog.bash
$(FEED_TARGET): $(COMITIUM_DATA)/feeds.txt $(FEED_TARGET): $(COMITIUM_DATA)/feeds.txt
rm -f $(COMITIUM_DATA)/comitium.json rm -f $(FEED_TARGET); \
while read feed; do \ while read feed; do \
comitium add --data "$(COMITIUM_DATA)" $$feed; \ comitium add --data "$(COMITIUM_DATA)" $$feed; \
done <$(COMITIUM_DATA)/feeds.txt done <$(COMITIUM_DATA)/feeds.txt
+22
View File
@@ -0,0 +1,22 @@
GEMINI_COMITIUM_DATA_FILES := $(addprefix $(GEMINI_COMITIUM_DATA_DIR)/,$(notdir $(wildcard comitium-data/*)))
.PHONY: install
install: $(GEMINI_CERTIFICATES_DIR) $(GEMINI_COMITIUM_DATA_FILES)
.PHONY: reinstall
reinstall: $(GEMINI_CERTIFICATES_DIR) $(GEMINI_COMITIUM_DATA_FILES)
$(GEMINI_CERTIFICATES_DIR):
sudo mkdir -p $(GEMINI_CERTIFICATES_DIR)
$(let gemini_user,$(shell whoami),sudo chown -R $(gemini_user):$(gemini_user) $(GEMINI_CERTIFICATES_DIR))
$(GEMINI_COMITIUM_DATA_DIR)/%: comitium-data/% $(GEMINI_COMITIUM_DATA_DIR)
sudo cp $< $@
$(let gemini_user,$(shell whoami),sudo chown $(gemini_user):$(gemini_user) $@)
$(GEMINI_COMITIUM_DATA_DIR):
sudo mkdir -p $(GEMINI_COMITIUM_DATA_DIR)
.PHONY: uninstall
uninstall:
sudo rm -rf $(GEMINI_COMITIUM_DATA_DIR)
+1 -2
View File
@@ -1,5 +1,4 @@
#!/bin/sh #!/bin/sh
make && \ ( ( sleep 5; comitium refresh --data comitium-data/ ) & ) \
( ( sleep 5; comitium refresh --data comitium-data/ ) & ) \
&& agate --content content/ --addr [::]:1965 --addr 0.0.0.0:1965 --lang en-GB && agate --content content/ --addr [::]:1965 --addr 0.0.0.0:1965 --lang en-GB
+12 -3
View File
@@ -1,4 +1,13 @@
FROM docker.io/arm32v7/nginx:1.30.3-alpine3.23 FROM docker.io/arm32v7/nginx:1.30.3-alpine3.23
RUN apk --update add php85-fpm RUN apk --update add php85-fpm php85-pdo php85-pdo_sqlite
WORKDIR /var/app COPY http/vendor /usr/share/nginx/vendor
COPY http/out http/php ./ COPY http/php /usr/share/nginx/php
COPY http/out /usr/share/nginx/html
COPY http/php-fpm.conf /etc/php85/php-fpm.d/joeac.net-http_pool.conf
COPY http/nginx.conf /etc/nginx/nginx.conf
CMD mkdir -p "$(dirname "$DB_PATH")" \
&& touch $DB_PATH \
&& chown -R nginx:nginx "$(dirname "$DB_PATH")" \
&& chmod -R 700 "$(dirname "$DB_PATH")" \
&& php-fpm85 \
&& nginx -g "daemon off;"
+51 -24
View File
@@ -5,8 +5,7 @@ include config.mk
# VARIABLES # # VARIABLES #
############# #############
src_files := $(filter-out %.args,$(wildcard src/*.upp*)) src_files := $(filter-out %.args,$(wildcard src/*.upp*)) $(filter-out %.args,$(wildcard src/**/*.upp*))
src_files += $(filter-out %.args,$(wildcard src/**/*.upp*))
src_files_ext := $(suffix $(src_files)) src_files_ext := $(suffix $(src_files))
out_deps_ext := $(src_files_ext:.upp%=%) out_deps_ext := $(src_files_ext:.upp%=%)
@@ -14,10 +13,12 @@ component_files := $(shell find -L share/components -type f)
layout_files := $(wildcard share/layouts/*.layout.upp*) layout_files := $(wildcard share/layouts/*.layout.upp*)
layouts := $(notdir $(basename $(basename $(layout_files)))) layouts := $(notdir $(basename $(basename $(layout_files))))
out_deps := $(addprefix out/,$(src_files:src/%=%)) remove_all_layouts = $(call remove_layouts,$(layouts),$(1))
remove_layout_from_out_deps = out_deps := $$(subst $(1).upp,.,$$(out_deps)) remove_layouts = $(let first rest,$(1),$(call remove_layout,$(first),$(if $(rest),$(call remove_layouts,$(rest),$(2)),$(2))))
$(foreach layout,$(layouts),$(eval $(call remove_layout_from_out_deps,.$(layout)))) remove_layout = $(subst .$(1).upp,.,$(2))
$(eval $(call remove_layout_from_out_deps,)) out_deps := $(subst .upp,.,$(call remove_all_layouts,$(addprefix out/,$(src_files:src/%=%))))
out_deps_without_src := $(filter-out $(out_deps),$(shell find -L out -type f))
out_deps += $(out_deps_without_src)
blogs := $(subst blogs/,,$(wildcard blogs/*)) blogs := $(subst blogs/,,$(wildcard blogs/*))
@@ -32,24 +33,25 @@ blog_src = $(patsubst \
blogs/$(blog)/%.$(BLOG_EXT_$(blog)),\ blogs/$(blog)/%.$(BLOG_EXT_$(blog)),\
src/$(blog)/%$(if $(BLOG_LAYOUT_$(blog)),.$(BLOG_LAYOUT_$(blog))).upphtml,\ src/$(blog)/%$(if $(BLOG_LAYOUT_$(blog)),.$(BLOG_LAYOUT_$(blog))).upphtml,\
$(shell find -L "blogs/$(blog)" -type f -and -name *.$(BLOG_EXT_$(blog)))) $(shell find -L "blogs/$(blog)" -type f -and -name *.$(BLOG_EXT_$(blog))))
blog_src_without_post_src = $(filter-out $(blog_src),$(shell find -L "src/$(blog)" -type f -and -name *.$(BLOG_LAYOUT_$(blog)).upphtml))
default_layout_file = $(if \ default_layout_file = $(if \
$(shell [ -f "share/layouts/default.layout.$(ext)" ] && echo 1),\ $(shell [ -f "share/layouts/default.layout.$(ext)" ] && echo 1),\
share/layouts/default.layout.$(ext)) share/layouts/default.layout.$(ext))
layout_file = $(if $(layout),share/layouts/$(layout).layout.upp$(ext),$(default_layout_file)) layout_file = $(if $(layout),share/layouts/$(layout).layout.upp$(ext),$(default_layout_file))
define out_rule = define out_rule =
out/%.$(ext): src/%$(if $(layout),.$(layout)).upp$(ext) $(layout_file) $(component_files) out/%.$(ext): src/%$(if $(layout),.$(layout)).upp$(ext) $(layout_file) $(component_files) bin/pp
./bin/mkws https://joeac.net "$$$$(realpath $$<)" ./bin/mkws https://joeac.net "$$$$(realpath $$<)"
endef endef
define blog_rss_feed_rule = define blog_rss_feed_rule =
out/$(blog)/rss.xml: src/$(blog)/rss.uppxml $(blog_src) $(wildcard bin/*) out/$(blog)/rss.xml: src/$(blog)/rss.uppxml $(blog_src) $(wildcard bin/*) bin/pp
./bin/mkws https://joeac.net "$$(realpath src/$(blog)/rss.uppxml)" ./bin/mkws https://joeac.net "$$(realpath src/$(blog)/rss.uppxml)"
endef endef
define blog_rule = define blog_rule =
.PHONY: $(blog) .PHONY: $(blog)
$(blog): $(blog_src) $(blog): $(blog_src_without_post_src) $(blog_src) out/$(blog).html
endef endef
define blog_post_rule = define blog_post_rule =
@@ -61,10 +63,35 @@ $(blog_post_target): $(blog_post_src) $(let ext,html,$(layout_file) $(component_
-f $$*.$(BLOG_EXT_$(blog)) -f $$*.$(BLOG_EXT_$(blog))
endef endef
define prune_blog_rule = define blog_index_rule =
.PHONY: prune_$(blog) out/$(blog).html: src/$(blog).upphtml $(blog_src) $(wildcard bin/*) bin/pp
prune_$(blog): ./bin/mkws https://joeac.net "$$(realpath src/$(blog).upphtml)"
./bin/prune_blog $(blog) *$(if $(BLOG_LAYOUT_$(blog)),.$(BLOG_LAYOUT_$(blog))).upphtml endef
define prune_blog_src_file_rule =
$(let rel_basename,$(patsubst src/$(blog)/%.$(BLOG_LAYOUT_$(blog)).upphtml,%,$(file)),
blogs/$(blog)/$(rel_basename).$(BLOG_EXT_$(blog)):
rm $(file)
)
endef
define prune_blog_out_file_rule =
$(let rel_basename,$(patsubst src/$(blog)/%.$(BLOG_LAYOUT_$(blog)).upphtml,%,$(file)),
$(file):
rm out/$(rel_basename).html
)
endef
define prune_out_file_rule =
$(let orig_ext,$(patsubst .%,%,$(suffix $(file))),
$(let ext,$(patsubst upp%,%,$(orig_ext)),
$(let rel_basename,$(patsubst out/%.$(orig_ext),%,$(file)),
$(let src_file,src/$(rel_basename).upp$(ext),
$(let src_files_with_layouts,$(foreach layout,$(layouts),src/$(rel_basename).$(layout).upp$(ext)),
$(let public_file,public/$(rel_basename).$(orig_ext),
$(src_file) $(src_files_with_layouts) $(public_file):
rm $(file)
))))))
endef endef
@@ -72,10 +99,8 @@ endef
# RULES # # RULES #
######### #########
all: bin/pp prune $(blogs) public out all: $(blogs) public out vendor
$(MAKE) out # if blog posts have been pruned, outfiles must be re-calculated
bin/pp:
cd pp && $(MAKE) && cp pp ../bin/pp
share/man/man1/pp.1: share/man/man1/pp.1:
cp pp/pp.1 share/man/man1/pp.1 cp pp/pp.1 share/man/man1/pp.1
@@ -83,6 +108,9 @@ share/man/man1/pp.1:
.PHONY: out .PHONY: out
out: $(out_deps) out: $(out_deps)
bin/pp:
$(MAKE) --directory=pp && chmod +x pp/pp && cp pp/pp bin/pp
$(foreach ext,$(sort $(out_deps_ext)),\ $(foreach ext,$(sort $(out_deps_ext)),\
$(eval $(out_rule))) $(eval $(out_rule)))
$(foreach layout,$(layouts),\ $(foreach layout,$(layouts),\
@@ -90,6 +118,7 @@ $(foreach layout,$(layouts),\
$(eval $(out_rule)))) $(eval $(out_rule))))
$(foreach blog,$(blogs),$(eval $(blog_rule))) $(foreach blog,$(blogs),$(eval $(blog_rule)))
$(foreach blog,$(blogs),$(eval $(blog_index_rule)))
$(foreach blog,$(blogs),\ $(foreach blog,$(blogs),\
$(foreach layout,$(layouts),\ $(foreach layout,$(layouts),\
@@ -105,18 +134,16 @@ public: $(subst public/,out/,$(shell find -L public/ -type f))
out/%: public/% out/%: public/%
mkdir -p $(dir $@) && cp $< $@ mkdir -p $(dir $@) && cp $< $@
.PHONY: prune $(foreach file,$(out_deps_without_src),$(eval $(prune_out_file_rule)))
prune: $(addprefix prune_,$(blogs)) prune_out $(foreach blog,$(blogs),$(foreach file,$(blog_src_without_post_src),$(eval $(prune_blog_src_file_rule))))
.PHONY: prune_out vendor: composer.json composer.lock
prune_out: composer install
./bin/prune_out
$(foreach blog,$(blogs),$(eval $(prune_blog_rule)))
.PHONY: clean .PHONY: clean
clean: clean:
rm -rf \ rm -rf \
vendor \
out \ out \
$(foreach blog,$(blogs), \ $(foreach blog,$(blogs), \
$(foreach ext,upphtml upphtml.args,\ $(foreach ext,upphtml upphtml.args,\
+2 -2
View File
@@ -102,8 +102,8 @@ do
export POST_TITLE="$name" export POST_TITLE="$name"
cat "$entry" | eval "${postprocess_cmd}" > "$dest" cat "$entry" | eval "${postprocess_cmd}" > "$dest"
else else
export POST_TITLE="$(grep --regexp "^# " --max-count 1 "$entry" | cut -c3-)" export POST_TITLE="$(grep -e "^# " -m 1 "$entry" | cut -c3-)"
cat "$entry" | grep --regexp "^# " --invert-match | eval "$postprocess_cmd" > "$dest" cat "$entry" | grep -e "^# " -v | eval "$postprocess_cmd" > "$dest"
fi fi
cat "$entry" | eval "$extract_args_cmd" > "${dest}.args" cat "$entry" | eval "$extract_args_cmd" > "${dest}.args"
echo "Processed ${entry#$(dirname ${BLOGS})/} to ${dest#$(dirname ${SRC})/}" echo "Processed ${entry#$(dirname ${BLOGS})/} to ${dest#$(dirname ${SRC})/}"
-45
View File
@@ -1,45 +0,0 @@
#!/bin/sh -e
BLOG="$1"
BLOG_POST_PATTERN="${2:-*}"
SRC="$(realpath src)"
BLOGS="$(realpath blogs)"
LAYOUTS="$(realpath share/layouts)"
BLOG_DIR_IN_SRC="${SRC}/${BLOG}"
BLOG_EXT=gmi
for post in $(find "$BLOG_DIR_IN_SRC" -type f -and -name "$BLOG_POST_PATTERN")
do
last_segment="${post##*\.}"
if [ "$last_segment" = "args" ]
then
continue
fi
post_rel_path="$(echo "$post" | cut -c${#BLOG_DIR_IN_SRC}- | cut -c3-)"
post_basename_len=$(( ${#post_rel_path} - ( ${#last_segment} + 1 ) ))
post_basename="$(echo "${post_rel_path}" | cut -c1-${post_basename_len})"
post_src="${BLOGS}/${BLOG}/${post_basename}.${BLOG_EXT}"
if [ -f "$post_src" ]
then
continue
fi
penultimate_segment_len=$(( ${#post} - ( ${#last_segment} + 1 ) ))
penultimate_segment="$(echo "${post}" | cut -c1-${penultimate_segment_len})"
penultimate_segment="${penultimate_segment##*\.}"
post_basename_len=$(( ${#post_rel_path} - ( ${#last_segment} + ${#penultimate_segment} + 2 ) ))
post_basename="$(echo "${post_rel_path}" | cut -c1-${post_basename_len})"
if [ -f "${LAYOUTS}/${penultimate_segment}.layout.${last_segment}" ]
then
post_src="${BLOGS}/${BLOG}/${post_basename}.${BLOG_EXT}"
if [ -f "$post_src" ]
then
continue
fi
fi
echo "No source file found to match post ${post} in blog ${BLOG}: removing ${post}"
rm -f "$post" "${post}.args"
done
-32
View File
@@ -1,32 +0,0 @@
#!/bin/sh -e
for out in $(find out -type f)
do
out_basename="$(basename "$out")"
out_ext="${out_basename##*\.}"
rel_path="$(echo "${out}" | cut -c5-)"
if [ -f "public/${rel_path}" ]; then
continue
fi
base_rel_path="${rel_path%%.${out_ext}}"
src_path="src/${base_rel_path}.upp${out_ext}"
if [ -f "$src_path" ]; then
continue
fi
for layout in $(find share/layouts -name "*.layout.upp${out_ext}"); do
layout="$(basename "$layout")"
layout="$(echo ${layout} | cut -c1-$(( ${#layout} - 15 )) )"
rel_path="$(echo "${out}" | cut -c5-)"
base_rel_path="${rel_path%%.${out_ext}}"
src_path="src/${base_rel_path}.${layout}.upp${out_ext}"
if [ -f "$src_path" ]; then
continue 2
fi
done
echo "No source file found to match ${out}: removing it"
rm "$out"
done
+5 -5
View File
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "752c91265ea3414ab13b2ff0f8925706", "content-hash": "5145609ea1f80d6d838d0f9649acd36a",
"packages": [ "packages": [
{ {
"name": "phpmailer/phpmailer", "name": "phpmailer/phpmailer",
@@ -92,10 +92,10 @@
"packages-dev": [], "packages-dev": [],
"aliases": [], "aliases": [],
"minimum-stability": "stable", "minimum-stability": "stable",
"stability-flags": [], "stability-flags": {},
"prefer-stable": false, "prefer-stable": false,
"prefer-lowest": false, "prefer-lowest": false,
"platform": [], "platform": {},
"platform-dev": [], "platform-dev": {},
"plugin-api-version": "2.3.0" "plugin-api-version": "2.9.0"
} }
+47
View File
@@ -0,0 +1,47 @@
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
listen [::]:80;
server_name joeac.net;
access_log /var/log/nginx/host.access.log main;
location / {
root /usr/share/nginx/html;
try_files $uri $uri.html $uri/index.html $uri.php $uri/index.php =404;
}
error_page 404 /error.html;
location ~ \.php$ {
root html;
fastcgi_pass unix:/run/php8.5-fpm-joeac.net-http.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /usr/share/nginx/html$fastcgi_script_name;
include fastcgi_params;
}
location ~ /\.sqlite {
deny all;
}
}
}
+36
View File
@@ -0,0 +1,36 @@
[joeac.net]
user = nginx
group = nginx
listen = /run/php8.5-fpm-joeac.net-http.sock
listen.owner = nginx
listen.group = nginx
listen.mode = 0660
access.log = /var/log/php85/$pool.access.log
access.format = "%R - %u %t \"%m %r%Q%q\" %s %f %{milli}d %{kilo}M %C%%"
catch_workers_output = yes
php_admin_value[error_log] = /var/log/php85/$pool.error.log
php_admin_flag[log_errors] = on
php_admin_value[disable_functions] = exec,passthru,shell_exec,system
php_admin_flag[allow_url_fopen] = off
pm = dynamic
pm.max_children = 20
pm.start_servers = 4
pm.min_spare_servers = 2
pm.max_spare_servers = 8
pm.max_requests = 500
clear_env = no
env[MAX_DAILY_EMAILS] = $MAX_DAILY_EMAILS
env[CONTACT_MAILBOX] = $CONTACT_MAILBOX
env[CONTACT_MAILBOX_NAME] = $CONTACT_MAILBOX_NAME
env[LOCAL_SMTP_FROM] = $LOCAL_SMTP_FROM
env[LOCAL_SMTP_FROM_NAME] = $LOCAL_SMTP_FROM_NAME
env[LOCAL_SMTP_HOST] = $LOCAL_SMTP_HOST
env[LOCAL_SMTP_PORT] = $LOCAL_SMTP_PORT
env[LOCAL_SMTP_USER] = $LOCAL_SMTP_USER
env[LOCAL_SMTP_PASSWORD] = $LOCAL_SMTP_PASSWORD
env[DB_SCHEME] = $DB_SCHEME
env[DB_PATH] = $DB_PATH
+1 -1
View File
@@ -1,4 +1,4 @@
#! #!
SITE_URL="${1}" SITE_URL="${1}"
#! #!
<meta http-equiv="refresh" content="0" ; url="${SITE_URL}/subscribe" /> <meta http-equiv=refresh content=0;url=${SITE_URL}/subscribe />
+1 -1
View File
@@ -1,4 +1,4 @@
#! #!
SITE_URL="${1}" SITE_URL="${1}"
#! #!
<meta http-equiv="refresh" content="0" ; url="${SITE_URL}/microlog/rss.xml" /> <meta http-equiv=refresh content=0;url=${SITE_URL}/microlog/rss.xml />
+113
View File
@@ -0,0 +1,113 @@
#!/bin/sh
get_var_value()
{
expr "$(env | grep "^${1}=")" : "${1}=\(.*\)\$"
}
if [ -z "$(which podman 2>/dev/null)" ]
then
sudo apk add podman
fi
if [ -z "$(which podman-compose 2>/dev/null)" ]
then
sudo apk add podman-compose
fi
if [ -z "$(which yq 2>/dev/null)" ]
then
YQ_PLATFORM="linux_$(expr "$(arch)" : "armv7" && echo arm || expr "$(arch)" : "x86_64" && echo amd64 || arch)"
sudo wget -O /usr/local/bin/yq https://github.com/mikefarah/yq/releases/latest/download/yq_linux_${YQ_PLATFORM}
sudo chmod +x /usr/local/bin/yq
fi
if [ -z "$(which envsubst 2>/dev/null)" ]
then
if [ "$(arch)" = "x86_64" ] || [ "$(arch)" = "arm64" ]
then
ENVSUBST_VERSION=1.4.3
sudo wget -O /usr/local/bin/envsubst https://github.com/a8m/envsubst/releases/download/v${ENVSUBST_VERSION}/envsubst-Linux-$(arch)
sudo chmod +x /usr/local/bin/envsubst
else
sudo apk add go
go install github.com/a8m/envsubst/cmd/envsubst@latest
fi
fi
if [ -z "$(which bash 2>/dev/null)" ]
then
sudo apk add bash
fi
if [ -z "$(grep "\bjoeac.net\b" /etc/group)" ]
then
sudo adduser -D -h /home/joeac.net joeac.net
sudo adduser joeac.net joeac.net
fi
if ! ( expr "$(groups joeac.net)" wheel )
then
sudo adduser joeac.net wheel
fi
su -l joeac.net
if ! [ $(whoami) = "joeac.net" ]
then
echo "Could not log in to user: joeac.net. Log in manually and re-run this script as joeac.net."
exit 1
fi
if ! [ -d /home/joeac.net/joeac.net/.git ]
then
git clone https://git.joeac.net/joeac/joeac.net.git /home/joeac.net/joeac.net
fi
sudo chown joeac.net:joeac.net /home/joeac.net/joeac.net
sudo chmod 770 /home/joeac.netjoeac.net
if ! [ -f DIGITALOCEAN_TOKEN ]
then
if [ -z "${DIGITALOCEAN_TOKEN}" ]
then
read -sp "DIGITALOCEAN_TOKEN: " DIGITALOCEAN_TOKEN
fi
echo ${DIGITALOCEAN_TOKEN} > /home/joeac.net/joeac.net/DIGITALOCEAN_TOKEN
fi
if ! ( podman secret exists remote_smtp_password )
then
if [ -z "${REMOTE_SMTP_PASSWORD}" ]
then
read -sp "REMOTE_SMTP_PASSWORD: " REMOTE_SMTP_PASSWORD
fi
echo "${REMOTE_SMTP_PASSWORD}" | podman secret create remote_smtp_password -
unset REMOTE_SMTP_PASSWORD
fi
while read line
do
if expr "${line}" : "[[:alnum:]_]\+=" 1>/dev/null
then
var_name="$(expr "${line}" : "\([[:alnum:]_]\+\)=")"
if [ -n "$(grep "^${var_name}=" /home/joeac.net/joeac.net/.env)" ]
then
continue
fi
if [ -z "$(get_var_value ${var_name})" ]
then
default_value="$(expr "${line}" : "[[:alnum:]_]\+=\(.*\)\$")"
read -sp "${var_name}: " ${var_name}
if [ -z "$(get_var_value ${var_name})" ]
then
eval ${var_name}="${default_value}"
fi
fi
echo "${var_name}=$(get_var_value ${var_name})" >> /home/joeac.net/joeac.net/.env
fi
done </home/joeac.net/joeac.net/example.env
make --directory=/home/joeac.net/joeac.net
make --directory=/home/joeac.net/joeac.net install
+14
View File
@@ -0,0 +1,14 @@
.PHONY: install
install: $(PUBLIC_ROOT_DIR_ln)
.PHONY: reinstall
reinstall: install
$(PUBLIC_ROOT_DIR_ln): public
sudo rm -rf $(PUBLIC_ROOT_DIR_ln)
sudo mkdir -p $(PUBLIC_ROOT_DIR_ln)
sudo cp -r public/ $(PUBLIC_ROOT_DIR_ln)/
.PHONY: uninstall
uninstall:
sudo rm -rf $(PUBLIC_ROOT_DIR_ln)
+1
View File
@@ -0,0 +1 @@
<meta http-equiv="refresh" content="0;url=https://forms.zohopublic.eu/mejo1/form/MilehousehutJuly2026/formperma/Jzvv9p6KIJxon5_kc2l29tI0FiMjKy3bJ5ICS9K67NQ" />
+28
View File
@@ -0,0 +1,28 @@
REGISTRY_DOMAIN := git.joeac.net
REGISTRY_USER := joeac
container_image_name = $(shell $(COMPOSE_CMD) config | yq ".services.$(module).image")
is_containerised = $(filter $(COMPOSE_SERVICES),$(module))
is_own_image = $(filter git.joeac.net/%,$(container_image_name))
has_dockerfile = $(shell test -f $(module).Dockerfile)
define build_module_rule =
.PHONY: build_$(module)
build_$(module): $(if $(is_containerised),make_$(module) $(if $(has_dockerfile),$(module).Dockerfile))
$(if $(is_containerised),\
$(COMPOSE_CMD) build $(module))
endef
define push_module_rule =
.PHONY: push_$(module)
push_$(module): $(if $(is_containerised),login_registry)
$(if $(is_containerised),$(if $(is_own_image),\
podman push $(container_image_name)))
endef
$(foreach module,$(MODULES),$(eval $(call build_module_rule)))
$(foreach module,$(MODULES),$(eval $(call push_module_rule)))
.PHONY: login_registry
login_registry:
podman login $(REGISTRY_DOMAIN)
+13
View File
@@ -0,0 +1,13 @@
.PHONY: install_crontab
install_crontab: /etc/periodic/daily/joeac.net
.PHONY: reinstall_crontab
reinstall_crontab: /etc/periodic/daily/joeac.net
.PHONY: uninstall_crontab
uninstall_crontab:
sudo rm -f /etc/periodic/daily/joeac.net
/etc/periodic/daily/joeac.net: update.sh
sudo cp update.sh /etc/periodic/daily/joeac.net
sudo chmod +x /etc/periodic/daily/joeac.net
+55
View File
@@ -0,0 +1,55 @@
installed_dyndns_crontabs = $(wildcard /etc/periodic/daily/dyndns-*.joeac.net)
installed_dyndns_subdomains = $(installed_dyndns_crontabs:/etc/periodic/daily/dyndns-%.joeac.net=%)
dyndns_subdomains_to_remove = $(filter-out $(SUBDOMAINS),$(installed_dyndns_subdomains))
dyndns_crontabs_to_remove = $(dyndns_subdomains_to_remove:%=/etc/periodic/daily/dyndns-%.joeac.net)
define install_dyndns_module_rule =
.PHONY: install_dyndns_$(module)
install_dyndns_module_$(module): $(if $(SUBDOMAIN_$(module)),/etc/periodic/daily/dyndns-$(SUBDOMAIN_$(module)).joeac.net)
endef
define reinstall_dyndns_module_rule =
.PHONY: reinstall_dyndns_$(module)
reinstall_dyndns_$(module): $(if $(SUBDOMAIN_$(module)),/etc/periodic/daily/dyndns-$(SUBDOMAIN_$(module)).joeac.net reinstall_dyndns)
endef
define uninstall_dyndns_module_rule =
.PHONY: uninstall_dyndns_$(module)
uninstall_dyndns_$(module):
$(if $(SUBDOMAIN_$(module)), \
sudo rm -f /etc/periodic/daily/dyndns-$(SUBDOMAIN_$(module)).joeac.net
)
endef
$(foreach module,$(ALL_MODULES), $(eval $(install_dyndns_module_rule)))
$(foreach module,$(ALL_MODULES), $(eval $(reinstall_dyndns_module_rule)))
$(foreach module,$(ALL_MODULES), $(eval $(uninstall_dyndns_module_rule)))
.PHONY: remove_/etc/periodic/daily/dyndns-%.joeac.net
remove_/etc/periodic/daily/dyndns-%.joeac.net:
rm -f $(@:remove_%=%)
/etc/periodic/daily/dyndns-%joeac.net: ~/digitalocean_dyndns/dyndns.sh ~/.config/dyndns/DIGITALOCEAN_TOKEN
echo "#!/bin/sh" > crontab.tmp
echo " $(shell realpath ~)/digitalocean_dyndns/dyndns.sh 4 $(*F)joeac.net" >> crontab.tmp
echo "CONN_DEVICE_NAME=eth0 $(shell realpath ~)/digitalocean_dyndns/dyndns.sh 6 $(*F)joeac.net" >> crontab.tmp
sudo mv crontab.tmp $@
sudo chmod +x $@
.PHONY: reinstall_dyndns
reinstall_dyndns: $(addprefix remove_,$(dyndns_crontabs_to_remove))
.PHONY: uninstall_dyndns
uninstall_dyndns: $(foreach module,$(ALL_MODULES),$(uninstall_dyndns_$(module)))
sudo rm -rf \
~/digitalocean_dyndns/ \
~/.config/dyndns \
~/.cache/dyndns
~/digitalocean_dyndns/%:
git clone https://git.joeac.net/joeac/digitalocean_dyndns.git ~/digitalocean_dyndns
~/.config/dyndns/DIGITALOCEAN_TOKEN: DIGITALOCEAN_TOKEN
mkdir -p ~/.config/dyndns/
rm -f ~/.config/dyndns/DIGITALOCEAN_TOKEN
cp DIGITALOCEAN_TOKEN ~/.config/dyndns/DIGITALOCEAN_TOKEN
+75
View File
@@ -0,0 +1,75 @@
installed_nginx_sites = $(wildcard /etc/nginx/http.d/*.joeac.net.conf)
installed_nginx_subdomains = $(installed_nginx_sites:/etc/nginx/http.d/%.joeac.net.conf=%)
nginx_subdomains_to_remove = $(filter-out $(NGINX_SUBDOMAINS),$(installed_nginx_subdomains))
nginx_sites_to_remove = $(nginx_subdomains_to_remove:%=/etc/nginx/http.d/%.joeac.net.conf)
nginx_module_config_template = \
$(if $(PORT_$(module)),nginx/http.d/reverse_proxy.conf.template) \
$(if $(PUBLIC_ROOT_DIR_$(module)),nginx/http.d/static.conf.template)
nginx_module_config_template_args = \
CERTNAME=$(SUBDOMAIN_$(module)).joeac.net \
DOMAIN=$(if $(filter-out @,$(SUBDOMAIN_$(module))),$(SUBDOMAIN_$(module)).)joeac.net \
$(if $(PORT_$(module)),PORT=$(PORT_$(module)) HOST=$(HOST_$(module))) \
$(if $(PUBLIC_ROOT_DIR_$(module)),ROOT="$(PUBLIC_ROOT_DIR_$(module))")
define install_nginx_module_rule =
.PHONY: install_nginx_$(module)
install_nginx_$(module): $(if $(SUBDOMAIN_$(module)),/etc/nginx/http.d/$(SUBDOMAIN_$(module)).joeac.net.conf)
endef
define reinstall_nginx_module_rule =
.PHONY: reinstall_nginx_$(module)
reinstall_nginx_$(module): $(if $(SUBDOMAIN_$(module)),/etc/nginx/http.d/$(SUBDOMAIN_$(module)).joeac.net.conf)
endef
define uninstall_nginx_module_rule =
.PHONY: uninstall_nginx_$(module)
uninstall_nginx_$(module):
$(if $(SUBDOMAIN_$(module)),sudo rm -f /etc/nginx/http.d/$(SUBDOMAIN_$(module)).joeac.net.conf)
endef
define remove_nginx_site_rule =
remove_$(site):
sudo rm -f $(site)
endef
define nginx_module_config_rule =
/etc/nginx/http.d/$(SUBDOMAIN_$(module)).joeac.net.conf: $(nginx_module_config_template) /etc/nginx/http.d /etc/nginx/nginx.conf
$(nginx_module_config_template_args) envsubst -i $$< -o $$(notdir $$@).tmp
sudo cp $$(notdir $$@).tmp $$@
sudo rc-service nginx restart
endef
$(foreach module,$(ALL_MODULES),$(eval $(install_nginx_module_rule)))
$(foreach module,$(ALL_MODULES),$(eval $(reinstall_nginx_module_rule)))
$(foreach module,$(ALL_MODULES),$(eval $(uninstall_nginx_module_rule)))
$(foreach site,$(nginx_sites_to_remove),$(eval $(remove_nginx_site_rule)))
$(foreach module,$(ALL_NGINX_MODULES),$(eval $(nginx_module_config_rule)))
/etc/nginx/http.d:
sudo mkdir -p /etc/nginx/http.d
.PHONY: remove_/etc/nginx/http.d/%.joeac.net.conf
remove_/etc/nginx/http.d/%.joeac.net.conf:
rm -f $(@:remove_%=%)
.PHONY: install_nginx
install_nginx: /etc/nginx/nginx.conf $(addprefix install_nginx_,$(NGINX_MODULES))
.PHONY: reinstall_nginx
reinstall_nginx: /etc/nginx/nginx.conf $(add_prefix reinstall_nginx_,$(NGINX_MODULES)) $(addprefix remove_,$(nginx_sites_to_remove))
.PHONY: uninstall_nginx
uninstall_nginx: $(foreach module,$(NGINX_MODULES),uninstall_nginx_$(module))
ifeq ($(shell test -d /etc/nginx/nginx.joeac.net-backup && echo 1 || echo 0),0)
$(warn No nginx backup config detected: doing nothing)
else
sudo mv /etc/nginx/nginx.joeac.net-backup /etc/nginx/nginx.conf
sudo rc-service nginx restart
endif
/etc/nginx/nginx.conf: nginx/nginx.conf /etc/nginx/nginx.joeac.net-backup
sudo cp $< $@
sudo rc-service nginx restart
/etc/nginx/nginx.joeac.net-backup:
sudo mv /etc/nginx/nginx.conf /etc/nginx/nginx.joeac.net-backup
+74
View File
@@ -0,0 +1,74 @@
is_openrc_module = $(filter $(COMPOSE_SERVICES),$(module))
openrc_module_target = $(if $(is_openrc_module),~/.config/rc/init.d/joeac.net.$(module))
define install_openrc_module_rule =
.PHONY: install_openrc_$(module)
install_openrc_$(module): $(if $(is_openrc_module),$(openrc_module_target) openrc_add_$(module) openrc_start_$(module))
~/.config/rc/init.d/joeac.net.$(module): ~/.config/rc/init.d/joeac.net ~/.config/rc/runlevels/default
rm -f ~/.config/rc/init.d/joeac.net.$(module)
ln -s $(shell realpath ~)/.config/rc/init.d/joeac.net ~/.config/rc/init.d/joeac.net.$(module)
endef
define reinstall_openrc_module_rule =
.PHONY: reinstall_openrc_$(module)
reinstall_openrc_$(module): $(if $(is_openrc_module),$(openrc_module_target) openrc_restart_$(module))
endef
define uninstall_openrc_module_rule =
.PHONY: uninstall_openrc_$(module)
uninstall_openrc_$(module):
$(if $(is_openrc_module),\
rc-service -U joeac.net.$(module) stop; \
rc-update -U del joeac.net.$(module) default; \
rm -f ~/.config/rc/init.d/joeac.net.$(module); \
)
endef
define openrc_add_rule =
.PHONY: openrc_add_$(module)
openrc_add_$(module):
rc-update -U add joeac.net.$(module) default
endef
define openrc_start_rule =
.PHONY: openrc_start_$(module)
openrc_start_$(module):
rc-service -U joeac.net.$(module) start
endef
define openrc_restart_rule =
.PHONY: openrc_restart_$(module)
openrc_restart_$(module):
rc-service -U joeac.net.$(module) restart
endef
$(foreach module,$(ALL_MODULES),$(eval $(install_openrc_module_rule)))
$(foreach module,$(ALL_MODULES),$(eval $(reinstall_openrc_module_rule)))
$(foreach module,$(ALL_MODULES),$(eval $(uninstall_openrc_module_rule)))
$(foreach module,$(ALL_MODULES),$(eval $(openrc_add_rule)))
$(foreach module,$(ALL_MODULES),$(eval $(openrc_start_rule)))
$(foreach module,$(MODULES),$(eval $(openrc_restart_rule)))
~/.config/rc/init.d/joeac.net: openrc/init.d/joeac.net.template ~/.config/rc/init.d ~/.config/rc/runlevels/default /etc/init.d/user.$(USER) /etc/conf.d/user.$(USER)
rm -f ~/.config/rc/init.d/joeac.net; \
mkdir -p ~/.config/rc/init.d; \
COMPOSECMD="$(COMPOSE_CMD)" envsubst -i openrc/init.d/joeac.net.template -o ~/.config/rc/init.d/joeac.net
chmod +x ~/.config/rc/init.d/joeac.net
~/.config/rc/init.d:
mkdir -p ~/.config/rc/init.d
~/.config/rc/runlevels/default:
mkdir -p ~/.config/rc/runlevels/default
/etc/init.d/user.$(USER):
sudo ln -s /etc/init.d/user /etc/init.d/user.$(USER)
/etc/conf.d/user.$(USER): openrc/conf.d/user.template
USER=$(USER) envsubst -i openrc/conf.d/user.template -o openrc/conf.d/user.$(USER)
sudo mv openrc/conf.d/user.$(USER) /etc/conf.d/user.$(USER)
sudo rc-update add user.$(USER) default
.PHONY: uninstall_joeac.net_service
rm ~/.config/rc/joeac.net
+89
View File
@@ -0,0 +1,89 @@
installed_tls_crontabs = $(wildcard /etc/periodic/daily/tls-*.joeac.net)
installed_tls_crontab_subdomains = $(installed_tls_crontabs:/etc/periodic/daily/tls-%.joeac.net=%)
tls_crontab_subdomains_to_remove = $(filter-out $(SUBDOMAINS),$(installed_tls_crontab_subdomains))
tls_crontabs_to_remove = $(tls_crontab_subdomains_to_remove:%=/etc/periodic/daily/tls-%.joeac.net)
installed_tls_certs = $(wildcard /etc/letsencrypt/live/*.joeac.net)
installed_tls_cert_subdomains = $(installed_tls_certs:/etc/letsencrypt/live/%.joeac.net=%)
tls_cert_subdomains_to_delete = $(filter-out $(SUBDOMAINS),$(installed_tls_cert_subdomains))
tls_crontab = /etc/periodic/daily/tls-$(subdomain).joeac.net
tls_cert = /etc/letsencrypt/live/$(subdomain).joeac.net/fullchain.pem
define install_tls_subdomain_rule =
.PHONY: install_tls_$(subdomain)
install_tls_$(subdomain): $(tls_crontab) $(tls_cert)
endef
define reinstall_tls_subdomain_rule =
.PHONY: reinstall_tls_$(subdomain)
reinstall_tls_$(subdomain): $(tls_crontab) renew_$(tls_cert)
endef
define uninstall_tls_subdomain_rule =
.PHONY: uninstall_tls_$(subdomain)
uninstall_tls_$(subdomain): delete_cert_$(subdomain).joeac.net
$(if $(shell [ -f $(tls_crontab) ] && echo 1),\
sudo rm -f $(tls_crontab)
)
endef
define obtain_or_renew_cert_cmd =
sudo certbot certonly \
--nginx \
--cert-name $(subdomain).joeac.net \
--domain $(subst @.,,$(subdomain).)joeac.net \
--non-interactive \
&& sudo chown -R joeac.net:joeac.net $(dir $(tls_cert))
endef
is_cert_expired = $(shell sudo certbot certificates --cert-name $(subdomain).joeac.net \
| grep "Expiry Date" | grep -E "(EXPIRED|REVOKED)")
define cert_rule =
$(tls_cert):
$(obtain_or_renew_cert_cmd)
.PHONY: renew_$(tls_cert)
renew_$(tls_cert):
$$(if $$(is_cert_expired),$(obtain_or_renew_cert_cmd))
endef
$(foreach subdomain,$(ALL_SUBDOMAINS), $(eval $(install_tls_subdomain_rule)))
$(foreach subdomain,$(ALL_SUBDOMAINS), $(eval $(reinstall_tls_subdomain_rule)))
$(foreach subdomain,$(ALL_SUBDOMAINS), $(eval $(uninstall_tls_subdomain_rule)))
$(foreach subdomain,$(ALL_SUBDOMAINS), $(eval $(cert_rule)))
.PHONY: remove_/etc/periodic/daily/tls-%.joeac.net
remove_/etc/periodic/daily/tls-%.joeac.net:
rm -f $(@:remove_%=%)
.PHONY: delete_cert_%
delete_cert_%:
sudo certbot delete --cert-name $(@:delete_cert_%=%).joeac.net --non-interactive
/etc/periodic/daily/tls-%joeac.net:
echo "#!/bin/sh" > crontab.tmp
echo "$(obtain_or_renew_cert_cmd)" >> crontab.tmp
sudo mv crontab.tmp $@
sudo chmod +x $@
certs_to_renew = $(foreach subdomain,$(filter $(SUBDOMAINS),$(installed_tls_cert_subdomains)),$(tls_cert))
tls_crontabs_to_install = $(foreach subdomain,$(SUBDOMAINS),$(tls_crontab))
tls_certs_to_install = $(foreach subdomain,$(SUBDOMAINS),$(tls_cert))
.PHONY: install_tls
install_tls: $(tls_crontabs_to_install) $(tls_certs_to_install) $(addprefix remove_,$(tls_crontabs_to_remove)) $(addprefix delete_cert_,$(tls_cert_subdomains_to_delete)) $(addprefix renew_,$(certs_to_renew))
.PHONY: reinstall_tls
reinstall_tls: install_tls
.PHONY: uninstall_tls
uninstall_tls: $(foreach subdomain,$(ALL_SUBDOMAINS),$(uninstall_tls_$(subdomain)))
.PHONY: install_certbot
install_certbot: /usr/bin/certbot /usr/bin/python /usr/lib/$(shell ls /usr/bin | grep python[0-9]\\.)/certbot_nginx
/usr/bin/certbot /usr/bin/python:
sudo apk add certbot
/usr/lib/python%/certbot_nginx:
sudo apk add certbot-nginx
+91
View File
@@ -0,0 +1,91 @@
capitalise = $(shell echo "$(1)" | tr '[:lower:]' '[:upper:]')
USER := $(shell whoami)
HOSTNAME := $(shell cat /etc/hostname)
HOSTNAMES := pi-broughton blade-canongate
IP_ADDR_pi-broughton := 192.168.178.54
IP_ADDR_blade-canongate := 192.168.178.75
MASTER_NODE := blade-canongate
IS_MASTER_NODE := $(filter $(MASTER_NODE),$(HOSTNAME))
MODULES_pi-broughton := actualbudget http smtp vaultwarden ln
MODULES_blade-canongate := etherpad gemini mox mox_clientsettings mox_autoconfig mox_mta_sts
ALL_NGINX_MODULES := actualbudget http vaultwarden ln etherpad mox mox_clientsettings mox_autoconfig mox_mta_sts
NGINX_MODULES := $(if $(IS_MASTER_NODE),$(ALL_NGINX_MODULES))
MODULES := $(MODULES_$(HOSTNAME))
ALL_MODULES := $(sort $(foreach hostname,$(HOSTNAMES),$(MODULES_$(hostname))))
COMPOSE_SERVICES := $(shell podman-compose config \
| yq ".services | keys" --output-format csv --csv-separator " ")
MAKE_MODULES := $(foreach module,$(MODULES),\
$(shell [ -f $(module)/Makefile ] && echo $(module)))
SUBDOMAIN_actualbudget := budget
SUBDOMAIN_http := @
SUBDOMAIN_vaultwarden := pwd
SUBDOMAIN_etherpad := docs
SUBDOMAIN_ln := ln
SUBDOMAIN_mox := mail
SUBDOMAIN_mox_autoconfig := autoconfig.mail
SUBDOMAIN_mox_clientsettings := clientsettings.mail
SUBDOMAIN_mox_mta_sts := mta-sts.mail
PORT_actualbudget := 5006
PORT_etherpad := 9001
PORT_http := 8080
PORT_gemini := 1965
PORT_mox := 81
PORT_mox_autoconfig := $(PORT_mox)
PORT_mox_clientsettings := $(PORT_mox)
PORT_mox_mta_sts := $(PORT_mox)
PORT_smtp := 2500
PORT_vaultwarden := 9000
PUBLIC_ROOT_DIR_ln := /var/ln.joeac.net/public
export ACTUALBUDGET_DATA_DIR := /var/joeac.net-actualbudget/var
export ETHERPAD_DATA_DIR := /var/etherpad/var
export GEMINI_CERTIFICATES_DIR := /var/joeac.net-gemini/certificates
export GEMINI_COMITIUM_DATA_DIR := /var/joeac.net-gemini/comitium-data
export VAULTWARDEN_DATA_DIR := /var/vaultwarden/data
ALPINE_VERSION := 3.23
ETHERPAD_VERSION := 3.3.2
$(foreach module,$(ALL_MODULES),$(if $(PORT_$(module)),$(eval \
export $(call capitalise,$(module))_PORT := $(PORT_$(module)))))
$(foreach hostname,$(HOSTNAMES),$(foreach module,$(MODULES_$(hostname)),$(eval \
export HOST_$(module) := $(if $(filter $(HOSTNAME),$(hostname)),127.0.0.1,$(IP_ADDR_$(hostname))))))
ALL_SUBDOMAINS := $(foreach module,$(ALL_MODULES),$(SUBDOMAIN_$(module)))
SUBDOMAINS := $(if $(IS_MASTER_NODE),$(ALL_SUBDOMAINS))
NGINX_SUBDOMAINS := $(foreach module,$(NGINX_MODULES),$(SUBDOMAIN_$(module)))
ENV_RULES := $(foreach module,$(MODULES),$(if $(shell test -d $(module) && echo 1),$(module)/.env))
MAKE_RULES := $(foreach module,$(MAKE_MODULES),make_$(module))
BUILD_RULES := $(foreach module,$(filter $(COMPOSE_SERVICES),$(MODULES)),build_$(module))
PUSH_RULES := $(foreach module,$(filter $(COMPOSE_SERVICES),$(MODULES)),push_$(module))
INSTALL_RULES := $(foreach module,$(MODULES),install_$(module))
REINSTALL_RULES := $(foreach module,$(MODULES),reinstall_$(module))
UNINSTALL_RULES := $(foreach module,$(MODULES),uninstall_$(module))
CPU_ARCH := $(if $(shell which arch 2>/dev/null),\
$(shell arch),\
$(shell lscpu | grep ^Architecture: | sed "s/^Architecture:[[:space:]]*\([[:alnum:][:punct:]]\+\).*/\1/"))
IMAGE_PREFIX := $(if $(filter armv7%,$(CPU_ARCH)),armv7/)
COMPOSE_CMD := \
ALPINE_VERSION="$(ALPINE_VERSION)" \
IMAGE_PREFIX="$(IMAGE_PREFIX)" \
GEMINI_CERTIFICATES_DIR="$(GEMINI_CERTIFICATES_DIR)" \
GEMINI_COMITIUM_DATA_DIR="$(GEMINI_COMITIUM_DATA_DIR)" \
ETHERPAD_DATA_DIR="$(ETHERPAD_DATA_DIR)" \
ETHERPAD_VERSION="$(ETHERPAD_VERSION)" \
VAULTWARDEN_DATA_DIR="$(VAULTWARDEN_DATA_DIR)" \
LOCAL_SMTP_PORT=$(PORT_smtp) \
$(foreach module,$(ALL_MODULES),$(call capitalise,$(module))_PORT=$(PORT_$(module))) \
podman-compose
$(foreach module,$(ALL_NGINX_MODULES), \
$(if $(SUBDOMAIN_$(module)),, \
$(error $(module) is declared as an nginx module, but SUBDOMAIN_$(module) is not set)))
$(foreach module,$(ALL_NGINX_MODULES), \
$(if $(PORT_$(module)) $(HOST_$(module)),,$(if $(PUBLIC_ROOT_DIR_$(module)),, \
$(error $(module) is declared as an nginx module, but neither PUBLIC_ROOT_DIR_$(module), nor both PORT_$(module) and HOST_$(module), are set))))
+2
View File
@@ -0,0 +1,2 @@
config/dkim
config/adminpasswd
+6
View File
@@ -0,0 +1,6 @@
# mox
There are three secrets required for mox. One is the admin password, which
should be stored in config/adminpasswd. The other two are DKIM private keys,
which should be stored in the config/dkim directory. The public parts of these
keys should be exposed in DNS TXT records.
+52
View File
@@ -0,0 +1,52 @@
Domains:
mail.joeac.net:
ClientSettingsDomain: clientsettings.mail.joeac.net
LocalpartCatchallSeparator: +
DKIM:
Selectors:
2026a:
Expiration: 72h
PrivateKeyFile: dkim/2026a._domainkey.mail.joeac.net.20260705T163220.rsa2048.privatekey.pkcs8.pem
2026b:
Expiration: 72h
PrivateKeyFile: dkim/2026b._domainkey.mail.joeac.net.20260705T163220.rsa2048.privatekey.pkcs8.pem
Sign:
- 2026a
DMARC:
Localpart: dmarcreports
Account: me
Mailbox: DMARC
MTASTS:
PolicyID: 20260705T153220
Mode: enforce
MaxAge: 24h0m0s
MX:
- mail.joeac.net
TLSRPT:
Localpart: tlsreports
Account: me
Mailbox: TLSRPT
Accounts:
me:
Domain: mail.joeac.net
Destinations:
me@mail.joeac.net: nil
SubjectPass:
Period: 12h0m0s
RejectsMailbox: Rejects
AutomaticJunkFlags:
Enabled: true
JunkMailboxRegexp: ^(junk|spam)
NeutralMailboxRegexp: ^(inbox|neutral|postmaster|dmarc|tlsrpt|rejects)
JunkFilter:
Threshold: 0.950000
Params:
Onegrams: true
MaxPower: 0.010000
TopWords: 10
IgnoreWords: 0.100000
RareWords: 2
NoCustomPassword: true
MonitorDNSBLs:
- zen.spamhaus.org
- bl.spamcop.net
+74
View File
@@ -0,0 +1,74 @@
DataDir: ../data
LogLevel: debug
User: mox
Hostname: mail.joeac.net
AdminPasswordFile: adminpasswd
Listeners:
internal:
IPs:
- 127.0.0.1
- ::1
Hostname: localhost
AccountHTTP:
Enabled: true
Port: 1080
Forwarded: true
AdminHTTP:
Enabled: true
Port: 1080
Forwarded: true
WebmailHTTP:
Enabled: true
Port: 1080
Forwarded: true
WebAPIHTTP:
Enabled: true
Port: 1080
Forwarded: true
MetricsHTTP:
Enabled: true
AutoconfigHTTPS:
Enabled: true
Port: 81
NonTLS: true
MTASTSHTTPS:
Enabled: true
Port: 81
NonTLS: true
WebserverHTTP:
Enabled: true
Port: 81
public:
IPs:
- 192.168.178.75
- fdc9:6aec:7a18:0:2e0:4cff:fe61:9b17
NATIPs:
- 217.155.190.42
- fdc9:6aec:7a18:0:2e0:4cff:fe61:9b17
TLS:
KeyCerts:
-
CertFile: /etc/letsencrypt/live/mail.joeac.net/fullchain.pem
KeyFile: /etc/letsencrypt/live/mail.joeac.net/privkey.pem
-
CertFile: /etc/letsencrypt/live/mta-sts.mail.joeac.net/fullchain.pem
KeyFile: /etc/letsencrypt/live/mta-sts.mail.joeac.net/privkey.pem
-
CertFile: /etc/letsencrypt/live/autoconfig.mail.joeac.net/fullchain.pem
KeyFile: /etc/letsencrypt/live/autoconfig.mail.joeac.net/privkey.pem
-
CertFile: /etc/letsencrypt/live/clientsettings.mail.joeac.net/fullchain.pem
KeyFile: /etc/letsencrypt/live/clientsettings.mail.joeac.net/privkey.pem
SMTP:
Enabled: true
Submissions:
Enabled: true
IMAPS:
Enabled: true
Postmaster:
Account: me
Mailbox: Postmaster
HostTLSRPT:
Account: me
Mailbox: TLSRPT
Localpart: tlsreports
+8
View File
@@ -0,0 +1,8 @@
server:
auto-trust-anchor-file: /var/lib/unbound/root.key
qname-minimisation: yes
interface: 0.0.0.0
access-control: 192.168.0.0/16 allow
remote-control:
control-enable: yes
+63
View File
@@ -0,0 +1,63 @@
.PHONY: install
install: install_unbound install_mox
.PHONY: reinstall
reinstall: install_unbound install_mox
.PHONY: install_unbound
install_unbound: /usr/sbin/unbound /etc/resolv.conf /var/lib/unbound/root.key install_unbound_anchor_crontab /etc/unbound/unbound.conf.d/dnssec.conf
/usr/sbin/unbound:
sudo apk add unbound
sudo rc-update add unbound default
sudo rc-service unbound start
/etc/resolv.conf: resolv.conf /etc/resolv.conf.joeac.net-backup
sudo cp resolv.conf /etc/resolv.conf
/etc/resolv.conf.joeac.net-backup:
sudo mv /etc/resolv.conf /etc/resolv.conf.joeac.net-backup
/var/lib/unbound/root.key:
sudo mkdir -p /var/lib/unbound && sudo unbound-anchor -a /var/lib/unbound/root.key
UNBOUND_ANCHOR_CRONTAB_ENTRY := @reboot unbound-anchor -a /var/lib/unbound/root.key # managed by joeac.net
IS_CRONTAB_UP_TO_DATE := $(sudo grep "$(UNBOUND_ANCHOR_CRONTAB_ENTRY)" /etc/crontabs/root)
.PHONY: install_unbound_anchor_crontab
install_unbound_anchor_crontab:
$(if $(IS_CRONTAB_UP_TO_DATE),,\
sudo crontab -l > crontab.tmp; \
sed -i "s/.*unbound-anchor.*# managed by joeac.net//" crontab.tmp; \
echo "$(UNBOUND_ANCHOR_CRONTAB_ENTRY)" >> crontab.tmp; \
sudo crontab crontab.tmp; \
rm crontab.tmp; \
)
/etc/unbound/unbound.conf.d/dnssec.conf: dnssec.conf
sudo mkdir -p $(dir $@) && sudo cp $< $@
DKIM_PRIVATE_KEY_A := ~/mox/config/dkim/2026a._domainkey.mail.joeac.net.20260705T163220.rsa2048.privatekey.pkcs8.pem
DKIM_PRIVATE_KEY_B := ~/mox/config/dkim/2026b._domainkey.mail.joeac.net.20260705T163220.rsa2048.privatekey.pkcs8.pem
DKIM_PRIVATE_KEYS := $(DKIM_PRIVATE_KEY_A) $(DKIM_PRIVATE_KEY_B)
MOX_TLS_CERTS := /etc/letsencrypt/live/mail.joeac.net/fullchain.pem /etc/letsencrypt/live/autoconfig.mail.joeac.net/fullchain.pem /etc/letsencrypt/live/clientsettings.mail.joeac.net/fullchain.pem /etc/letsencrypt/live/mta-sts.mail.joeac.net/fullchain.pem
.PHONY: install_mox
install_mox: /usr/local/bin/mox ~/mox/config/mox.conf ~/mox/config/domains.conf ~/mox/config/adminpasswd ~/mox/data $(DKIM_PRIVATE_KEYS) $(MOX_TLS_CERTS)
MOX_PLATFORM := $(if $(filter armv7% arm32%,$(CPU_ARCH)),arm,amd64)
MOX_VERSION := 0.0.15
MOX_GO_VERSION := 1.26.4
MOX_CHECKSUM_amd64_v0.0.15_go1.26.4 := 09OE-1QkNVgmpoRj53mtX9gxoEmY
MOX_CHECKSUM_arm_v0.0.15_go1.26.4 := 038X9nQx6hhai60Fk1BhcP3r6Mew
MOX_CHECKSUM := $(MOX_CHECKSUM_$(MOX_PLATFORM)_v$(MOX_VERSION)_go$(MOX_GO_VERSION))
MOX_URL_BASE := https://beta.gobuilds.org/github.com/mjl-/mox
MOX_URL := $(MOX_URL_BASE)@v$(MOX_VERSION)/linux-$(MOX_PLATFORM)-go$(MOX_GO_VERSION)/$(MOX_CHECKSUM)
/usr/local/bin/mox:
wget -O- $(MOX_URL) | gzip -d > mox
chmod +x mox
sudo mv mox /usr/local/bin/mox
~/mox/config/%: config/%
mkdir -p $(dir $@) && cp $< $@
~/mox/data:
mkdir -p $@
+1
View File
@@ -0,0 +1 @@
nameserver: 127.0.0.1
+20
View File
@@ -0,0 +1,20 @@
server {
server_name ${DOMAIN};
location / {
proxy_pass http://${HOST}:${PORT};
}
listen 443 ssl;
ssl_certificate /etc/letsencrypt/live/${DOMAIN}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/${DOMAIN}/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
}
server {
if ($$host = ${DOMAIN}) {
return 301 https://$$host$$request_uri;
}
server_name ${DOMAIN};
listen 80;
return 404;
}
+22
View File
@@ -0,0 +1,22 @@
server {
server_name ${DOMAIN};
location / {
root ${ROOT};
try_files $$uri $$uri.html $$uri/index.html =404;
error_page 404 /index.html;
}
listen 443 ssl;
ssl_certificate /etc/letsencrypt/live/${CERTNAME}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/${CERTNAME}/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
}
server {
if ($$host = ${DOMAIN}) {
return 301 https://$$host$$request_uri;
} # managed by Certbot
server_name ln.joeac.net;
listen 80;
return 404;
}
+99
View File
@@ -0,0 +1,99 @@
types {
text/html html htm shtml;
text/css css;
text/xml xml;
image/gif gif;
image/jpeg jpeg jpg;
application/javascript js;
application/atom+xml atom;
application/rss+xml rss;
text/mathml mml;
text/plain txt;
text/vnd.sun.j2me.app-descriptor jad;
text/vnd.wap.wml wml;
text/x-component htc;
image/avif avif;
image/png png;
image/svg+xml svg svgz;
image/tiff tif tiff;
image/vnd.wap.wbmp wbmp;
image/webp webp;
image/x-icon ico;
image/x-jng jng;
image/x-ms-bmp bmp;
font/woff woff;
font/woff2 woff2;
application/java-archive jar war ear;
application/json json;
application/mac-binhex40 hqx;
application/msword doc;
application/pdf pdf;
application/postscript ps eps ai;
application/rtf rtf;
application/vnd.apple.mpegurl m3u8;
application/vnd.google-earth.kml+xml kml;
application/vnd.google-earth.kmz kmz;
application/vnd.ms-excel xls;
application/vnd.ms-fontobject eot;
application/vnd.ms-powerpoint ppt;
application/vnd.oasis.opendocument.graphics odg;
application/vnd.oasis.opendocument.presentation odp;
application/vnd.oasis.opendocument.spreadsheet ods;
application/vnd.oasis.opendocument.text odt;
application/vnd.openxmlformats-officedocument.presentationml.presentation
pptx;
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
xlsx;
application/vnd.openxmlformats-officedocument.wordprocessingml.document
docx;
application/vnd.wap.wmlc wmlc;
application/wasm wasm;
application/x-7z-compressed 7z;
application/x-cocoa cco;
application/x-java-archive-diff jardiff;
application/x-java-jnlp-file jnlp;
application/x-makeself run;
application/x-perl pl pm;
application/x-pilot prc pdb;
application/x-rar-compressed rar;
application/x-redhat-package-manager rpm;
application/x-sea sea;
application/x-shockwave-flash swf;
application/x-stuffit sit;
application/x-tcl tcl tk;
application/x-x509-ca-cert der pem crt;
application/x-xpinstall xpi;
application/xhtml+xml xhtml;
application/xspf+xml xspf;
application/zip zip;
application/octet-stream bin exe dll;
application/octet-stream deb;
application/octet-stream dmg;
application/octet-stream iso img;
application/octet-stream msi msp msm;
audio/midi mid midi kar;
audio/mpeg mp3;
audio/ogg ogg;
audio/x-m4a m4a;
audio/x-realaudio ra;
video/3gpp 3gpp 3gp;
video/mp2t ts;
video/mp4 mp4;
video/mpeg mpeg mpg;
video/quicktime mov;
video/webm webm;
video/x-flv flv;
video/x-m4v m4v;
video/x-mng mng;
video/x-ms-asf asx asf;
video/x-ms-wmv wmv;
video/x-msvideo avi;
}
+33
View File
@@ -0,0 +1,33 @@
# /etc/nginx/nginx.conf
user nginx;
worker_processes auto;
pcre_jit on;
error_log /var/log/nginx/error.log warn;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
server_tokens off;
client_max_body_size 1m;
sendfile on;
tcp_nopush on;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:2m;
ssl_session_timeout 1h;
gzip on;
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
include /etc/nginx/http.d/*.conf;
}
+15
View File
@@ -0,0 +1,15 @@
UID="$$(id -u ${USER})"
if test -z "$${XDG_RUNTIME_DIR}"; then
export XDG_RUNTIME_DIR=/tmp/xdg/"$${UID}"-xdg-runtime-dir
if ! test -d "$${XDG_RUNTIME_DIR}"; then
mkdir -p "$${XDG_RUNTIME_DIR}"
chown -R ${USER}:${USER} "$${XDG_RUNTIME_DIR}"
chmod -R 0700 "$${XDG_RUNTIME_DIR}"
fi
fi
if ! test -f "$${XDG_RUNTIME_DIR}/openrc/softlevel"; then
mkdir -p "$${XDG_RUNTIME_DIR}/openrc"
touch "$${XDG_RUNTIME_DIR}/openrc/softlevel"
chown -R ${USER}:${USER} "$${XDG_RUNTIME_DIR}"
chmod -R 0700 "$${XDG_RUNTIME_DIR}"
fi
+65
View File
@@ -0,0 +1,65 @@
#!/sbin/openrc-run
# credits:
# https://gist.github.com/itzwam/2069e935385193207f7e5bea7156e21d
# https://github.com/0x17de/dockerservice-openrc
: $${HOME:=/home/joeac.net}
: $${MODULENAME:=$${RC_SVCNAME##*.}}
: $${SRCDIR:=$$HOME/joeac.net}
DOCKER_COMPOSE_UP_ARGS=$${DOCKER_COMPOSE_UP_ARGS-"--no-build --no-recreate --no-deps"}
[ -z "$${MODULENAME}" ] && exit 1
: $${COMPOSEFILE:="$${SRCDIR}/compose.yml"}
: $${MAKEFILE:="$${SRCDIR}/Makefile"}
export COMPOSE_HTTP_TIMEOUT=300
description="Manage dockerservices defined in $${COMPOSEFILE}"
extra_commands="configtest"
description_configtest="Check configuration via \"podman-compose -f $${COMPOSEFILE} config\""
configtest() {
if ! [ -f "$${COMPOSEFILE}" ]; then
eerror "The docker-compose file $${COMPOSEFILE} does not exist!"
return 1
fi
if ${COMPOSECMD} -f "$${COMPOSEFILE}" config >&/dev/null; then
einfo "config: ok"
else
eerror "config: error"
return 1
fi
}
start() {
configtest || return 1
ebegin "Starting $${MODULENAME}"
${COMPOSECMD} -f "$${COMPOSEFILE}" up -d $${DOCKER_COMPOSE_UP_ARGS} $${MODULENAME}
eend $$?
}
stop() {
ebegin "Stopping $${MODULENAME}"
${COMPOSECMD} -f "$${COMPOSEFILE}" down --timeout=5 $${MODULENAME}
eend $$?
}
status() {
pods=0
started=0
while read pod; do
pod_service="$$(podman inspect $$pod | jq .[0].Config.Labels.[\"com.docker.compose.service\"])"
if ! [ "$$pod_service" = "\"$${MODULENAME}\"" ]; then
continue
fi
pods=$$(($$pods+1))
if podman top $$pod &>/dev/null; then
einfo "status: [$$pod] started"
exit 0
else
einfo "status: [$$pod] stopped"
exit 3
fi
done < <(${COMPOSECMD} -f "$${COMPOSEFILE}" ps --quiet)
einfo "status: no container found for $${MODULENAME}"
exit 3
}
+5
View File
@@ -0,0 +1,5 @@
FROM git.joeac.net/joeac/armv7/msmtp:1.8.32-alpine3.23
RUN apk --no-cache add gettext gnutls
ARG SMTP_PORT
EXPOSE $SMTP_PORT
COPY smtp/.msmtprc ./
-4
View File
@@ -1,4 +0,0 @@
FROM git.joeac.net/joeac/armv7/msmtp:1.8.32-alpine3.23
ARG LOCAL_SMTP_PORT
EXPOSE $LOCAL_SMTP_PORT
COPY .msmtprc ./
+11
View File
@@ -0,0 +1,11 @@
#!/bin/sh
if [ -z "${XDG_RUNTIME_DIR}" ]
then
export XDG_RUNTIME_DIR=/tmp/xdg/$(id -u joeac.net)-xdg-runtime-dir
fi
cd /home/joeac.net/joeac.net \
&& sudo -u joeac.net git pull \
&& sudo -u joeac.net make \
&& sudo -u joeac.net make reinstall
+13
View File
@@ -0,0 +1,13 @@
.PHONY: install
install: $(VAULTWARDEN_DATA_DIR)
.PHONY: reinstall
reinstall: $(VAULTWARDEN_DATA_DIR)
$(VAULTWARDEN_DATA_DIR):
sudo mkdir -p $(VAULTWARDEN_DATA_DIR)
VAULTWARDEN_USER=$(whoami) && sudo chown $$VAULTWARDEN_USER:$$VAULTWARDEN_USER $(VAULTWARDEN_DATA_DIR)
.PHONY: uninstall
uninstall:
$(info Nothing to do)