nomad

HCL and Docker files for Nomad deployments
git clone https://git.in0rdr.ch/nomad.git
Log | Files | Refs | Pull requests |Archive

commit 7055991a7e134dcd6f5d4965bc9acd6ac9ca08a2
parent 5ec9e9bb454dbc99a6ddf2245b1de12a72febf85
Author: Andreas Gruhler <agruhl@gmx.ch>
Date:   Sat,  2 Aug 2025 23:14:59 +0200

feat(snac): add snac 🍕 job

Diffstat:
Ahcl/default/snac/data-volume.hcl | 31+++++++++++++++++++++++++++++++
Ahcl/default/snac/snac.nomad | 107+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ahcl/default/snac/templates/greeting.html.tmpl | 16++++++++++++++++
Ahcl/default/snac/templates/nginx.conf.tmpl | 72++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ahcl/default/snac/templates/server.json.tmpl | 28++++++++++++++++++++++++++++
Ahcl/default/snac/templates/style.css.tmpl | 40++++++++++++++++++++++++++++++++++++++++
6 files changed, 294 insertions(+), 0 deletions(-)

diff --git a/hcl/default/snac/data-volume.hcl b/hcl/default/snac/data-volume.hcl @@ -0,0 +1,31 @@ +# Register external nfs volume with Nomad CSI +# https://www.nomadproject.io/docs/commands/volume/register +type = "csi" +# Unique ID of the volume, volume.source field in a job +id = "snac" +# Display name of the volume. +name = "snac" +# ID of the physical volume from the storage provider +external_id = "csi-snac" +plugin_id = "nfs" + +# You must provide at least one capability block +# You must provide a block for each capability +# youintend to use in a job's volume block +# https://www.nomadproject.io/docs/commands/volume/register +capability { + access_mode = "multi-node-multi-writer" + attachment_mode = "file-system" +} + +# https://github.com/kubernetes-csi/csi-driver-nfs/blob/master/docs/driver-parameters.md +context { + server = "turris" + share = "csi-snac" +} + +mount_options { + # mount.nfs: Either use '-o nolock' to keep locks local, or start statd. + mount_flags = ["nolock"] +} + diff --git a/hcl/default/snac/snac.nomad b/hcl/default/snac/snac.nomad @@ -0,0 +1,107 @@ +# https://git.snac.social/snac/snac-docker-compose + +job "snac" { + datacenters = ["dc1"] + + vault {} + + group "server" { + count = 1 + + volume "tls" { + type = "csi" + source = "certbot" + access_mode = "multi-node-multi-writer" + attachment_mode = "file-system" + } + volume "snac" { + type = "csi" + source = "snac" + access_mode = "multi-node-multi-writer" + attachment_mode = "file-system" + } + + network { + port "http" { + to = 8001 + } + port "https" { + static = 44411 + } + } + + task "nginx" { + driver = "podman" + + config { + image = "docker.io/library/nginx:stable-alpine" + ports = ["https"] + volumes = [ + # mount the templated config from the task directory to the container + "local/snac.conf:/etc/nginx/conf.d/snac.conf", + ] + } + + volume_mount { + volume = "tls" + destination = "/etc/letsencrypt" + } + + template { + destination = "${NOMAD_TASK_DIR}/snac.conf" + data = file("./templates/nginx.conf.tmpl") + } + + resources { + memory = 50 + memory_max = 256 + cpu = 200 + } + } + + task "snac" { + driver = "podman" + + config { + image = "127.0.0.1:5000/snac:2.81" + force_pull = true + ports = ["http"] + volumes = [ + # mount the templated config from the task directory to the container + "local/greeting.html:/data/data/greeting.html", + "local/server.json:/data/data/server.json", + "local/style.css:/data/data/style.css" + ] + } + + env { + # https://comam.es/snac-doc/snac.8.html#ENVIRONMENT + #DEBUG = 100 + } + + volume_mount { + volume = "snac" + destination = "/data/data" + } + + template { + destination = "${NOMAD_TASK_DIR}/greeting.html" + data = file("./templates/greeting.html.tmpl") + } + template { + destination = "${NOMAD_TASK_DIR}/server.json" + data = file("./templates/server.json.tmpl") + } + template { + destination = "${NOMAD_TASK_DIR}/style.css" + data = file("./templates/style.css.tmpl") + } + + resources { + memory = 512 + memory_max = 1024 + cpu = 500 + } + } + } +} diff --git a/hcl/default/snac/templates/greeting.html.tmpl b/hcl/default/snac/templates/greeting.html.tmpl @@ -0,0 +1,16 @@ +<!DOCTYPE html> +<html><head> +<meta name="viewport" content="width=device-width, initial-scale=1"/> +<link rel="icon" type="image/x-icon" href="https://%host%/favicon.ico"/> +<style>*{color-scheme:light dark}body{margin:auto;max-width:50em}</style> +<title>Welcome to %host%</title> +</head> +<body> +<p><b>%host%</b> is a <a href="https://en.wikipedia.org/wiki/Fediverse">Fediverse</a> instance that uses the <a href="https://en.wikipedia.org/wiki/ActivityPub">ActivityPub</a> protocol. In other words, users at this host can communicate with people that use software like Mastodon, Pleroma, Friendica, etc. all around the world.</p> +<p>This server runs the <a href="https://comam.es/what-is-snac">snac</a> software and there is no automatic sign-up process.</p> +<p>The following users are part of this community:</p> + +%userlist% + +<p>This site is powered by <abbr title="Social Networks Are Crap">snac</abbr>.</p> +</body></html> diff --git a/hcl/default/snac/templates/nginx.conf.tmpl b/hcl/default/snac/templates/nginx.conf.tmpl @@ -0,0 +1,72 @@ +# https://comam.es/snac-doc/snac.8.html#EXAMPLES +# https://codeberg.org/grunfink/snac2/src/branch/master/examples/nginx-alpine-ssl/default.conf + +upstream snac { + server {{ env "NOMAD_ADDR_http" }} max_fails=5 fail_timeout=60s; +} + +server { + listen {{ env "NOMAD_PORT_https" }} ssl http2 default_server; + listen [::]:{{ env "NOMAD_PORT_https" }} ssl http2 default_server; + + # SSL configuration + ssl_certificate /etc/letsencrypt/live/m.in0rdr.ch/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/m.in0rdr.ch/privkey.pem; + + location /.well-known/webfinger { + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_redirect off; + proxy_connect_timeout 90; + proxy_send_timeout 90; + proxy_read_timeout 90; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header Proxy ""; + proxy_pass_header Server; + proxy_buffering on; + tcp_nodelay on; + proxy_pass http://snac; + } + + location /.well-known/nodeinfo { + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_redirect off; + proxy_connect_timeout 90; + proxy_send_timeout 90; + proxy_read_timeout 90; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header Proxy ""; + proxy_pass_header Server; + proxy_buffering on; + tcp_nodelay on; + proxy_pass http://snac; + } + + location / { + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_redirect off; + proxy_connect_timeout 90; + proxy_send_timeout 90; + proxy_read_timeout 90; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header Proxy ""; + proxy_pass_header Server; + proxy_buffering on; + tcp_nodelay on; + proxy_pass http://snac; + } +} diff --git a/hcl/default/snac/templates/server.json.tmpl b/hcl/default/snac/templates/server.json.tmpl @@ -0,0 +1,28 @@ +{ + "host": "m.in0rdr.ch", + "prefix": "", + "address": "0.0.0.0", + "port": 8001, + "layout": 2.7, + "dbglevel": 0, + "queue_retry_minutes": 2, + "queue_retry_max": 10, + "queue_timeout": 6, + "queue_timeout_2": 8, + "cssurls": [ + "" + ], + "def_timeline_entries": 50, + "max_timeline_entries": 50, + "timeline_purge_days": 120, + "local_purge_days": 0, + "min_account_age": 0, + "admin_email": "", + "admin_account": "in0rdr", + "title": "", + "short_description": "", + "short_description_raw": false, + "protocol": "https", + "fastcgi": false, + "disable_sandbox": false +} diff --git a/hcl/default/snac/templates/style.css.tmpl b/hcl/default/snac/templates/style.css.tmpl @@ -0,0 +1,39 @@ +body { max-width: 48em; margin: auto; line-height: 1.5; padding: 0.8em; word-wrap: break-word; } +pre { overflow-x: scroll; } +blockquote { font-style: italic; } +.snac-embedded-video, img { max-width: 100% } +.snac-origin { font-size: 85% } +.snac-score { float: right; font-size: 85% } +.snac-top-user { text-align: center; padding-bottom: 2em } +.snac-top-user-name { font-size: 200% } +.snac-top-user-id { font-size: 150% } +.snac-announcement { border: black 1px solid; padding: 0.5em } +.snac-avatar { float: left; height: 2.5em; width: 2.5em; padding: 0.25em } +.snac-author { font-size: 90%; text-decoration: none } +.snac-author-tag { font-size: 80% } +.snac-pubdate { color: #a0a0a0; font-size: 90% } +.snac-top-controls { padding-bottom: 1.5em } +.snac-post { border-top: 1px solid #a0a0a0; padding-top: 0.5em; padding-bottom: 0.5em; } +.snac-children { padding-left: 1em; border-left: 1px solid #a0a0a0; } +.snac-thread-cont { border-top: 1px dashed #a0a0a0; } +.snac-textarea { font-family: inherit; width: 100% } +.snac-history { border: 1px solid #606060; border-radius: 3px; margin: 2.5em 0; padding: 0 2em } +.snac-btn-mute { float: right; margin-left: 0.5em } +.snac-btn-unmute { float: right; margin-left: 0.5em } +.snac-btn-follow { float: right; margin-left: 0.5em } +.snac-btn-unfollow { float: right; margin-left: 0.5em } +.snac-btn-hide { float: right; margin-left: 0.5em } +.snac-btn-delete { float: right; margin-left: 0.5em } +.snac-btn-limit { float: right; margin-left: 0.5em } +.snac-btn-unlimit { float: right; margin-left: 0.5em } +.snac-footer { margin-top: 2em; font-size: 75% } +.snac-poll-result { margin-left: auto; margin-right: auto; } +.snac-list-of-lists { padding-left: 0; } +.snac-list-of-lists li { display: inline; border: 1px solid #a0a0a0; border-radius: 25px; + margin-right: 0.5em; padding-left: 0.5em; padding-right: 0.5em; } +.snac-no-more-unseen-posts { border-top: 1px solid #a0a0a0; border-bottom: 1px solid #a0a0a0; padding: 0.5em 0; margin: 1em 0; } +@media (prefers-color-scheme: dark) { + body, input, textarea { background-color: #000; color: #fff; } + a { color: #7799dd } + a:visited { color: #aa99dd } +} +\ No newline at end of file