267 lines
9.2 KiB
YAML
Executable File
267 lines
9.2 KiB
YAML
Executable File
variant: fcos
|
|
version: 1.6.0
|
|
# cirrus: 5001 admin sshd | 5002 sish SSH | 80 HTTP by Host | 443 TLS by SNI (passthrough)
|
|
# 22, 20000-20099 raw TCP forwards
|
|
|
|
passwd:
|
|
users:
|
|
- name: core
|
|
ssh_authorized_keys:
|
|
- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILL4RXmGVhbcCdh3a6TdgR+7EER250UUDk0VtrwUvb9E philipp@philipp-laptop
|
|
|
|
storage:
|
|
directories:
|
|
- path: /var/lib/sish/keys
|
|
mode: 0700
|
|
user: { id: 65532 }
|
|
group: { id: 65532 }
|
|
files:
|
|
- path: /etc/hostname
|
|
mode: 0644
|
|
contents:
|
|
inline: cirrus.traberph.de
|
|
# netcup: IPv4 via DHCP, IPv6 static (no router advertisements, gateway is always fe80::1)
|
|
- path: /etc/NetworkManager/system-connections/ens3.nmconnection
|
|
mode: 0600
|
|
contents:
|
|
inline: |
|
|
[connection]
|
|
id=ens3
|
|
type=ethernet
|
|
interface-name=ens3
|
|
|
|
[ipv4]
|
|
method=auto
|
|
|
|
[ipv6]
|
|
method=manual
|
|
address1=2a03:4000:2:83c::1/64
|
|
gateway=fe80::1
|
|
# Edge SSH host key (connectors pin its public half). Kept only locally in coreos/.secrets/
|
|
# (gitignored), so back it up outside this folder. Build: butane --files-dir coreos ...
|
|
- path: /var/lib/sish/keys/ssh_host_ed25519_key
|
|
mode: 0400
|
|
user: { id: 65532 }
|
|
group: { id: 65532 }
|
|
contents:
|
|
local: .secrets/ssh_host_ed25519_key
|
|
- path: /var/lib/sish/pubkeys/clients # k8s tunnel client keys (authorized_keys format)
|
|
mode: 0644
|
|
contents:
|
|
inline: |
|
|
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEsHP4H4HLHCEhycaAV+YZZV/HOr7HSiDkgpMA+WLO56 connector-cumulus
|
|
- path: /etc/ssh/sshd_config.d/10-cirrus.conf
|
|
mode: 0644
|
|
contents:
|
|
inline: |
|
|
Port 5001
|
|
AuthenticationMethods publickey
|
|
PermitRootLogin no
|
|
AllowUsers core
|
|
- path: /etc/cirrus/sshd_port_5001.cil # 5001 is commplex_link_port_t
|
|
mode: 0644
|
|
contents:
|
|
inline: |
|
|
(allow sshd_t commplex_link_port_t (tcp_socket (name_bind)))
|
|
# Same sish config as kubernetes/base/sish/config.yml (+ the cirrus overlay values),
|
|
# only the SSH port differs (5002 instead of 2222).
|
|
- path: /etc/sish/config.yml
|
|
mode: 0644
|
|
contents:
|
|
inline: |
|
|
# Listeners
|
|
ssh-address: ":5002"
|
|
http-address: ":80"
|
|
https: false # sish never terminates TLS; :443 is an SNI passthrough listener
|
|
|
|
# Single tenant: connectors may claim any hostname containing a dot, wildcards included
|
|
# (*.example.com). Only a name without a dot falls back to <name>.<domain>.
|
|
bind-any-host: true
|
|
verify-dns: false # _sish TXT ownership checks, pointless with bind-any-host
|
|
domain: tunnel.traberph.de # the edge's own name (A/AAAA -> VPS)
|
|
|
|
# SNI passthrough + multiple connectors per hostname
|
|
sni-proxy: true
|
|
sni-load-balancer: true
|
|
tcp-load-balancer: true
|
|
http-load-balancer: true
|
|
|
|
# Connectors get exactly what they ask for, or the bind fails
|
|
bind-random-ports: false
|
|
bind-random-subdomains: false
|
|
bind-random-aliases: false
|
|
force-requested-subdomains: true
|
|
force-requested-ports: true
|
|
bind-wildcards: true
|
|
# Ports connectors may claim. Must match the nftables rule below, otherwise a claimed
|
|
# port is silently unreachable.
|
|
# 22 gitea ssh, 443 SNI, 20000-20099 reserved for raw tcp forwards.
|
|
port-bind-range: "22,443,20000-20099"
|
|
|
|
# PROXY header version for connectors that request it (sish-client default: v2)
|
|
proxy-protocol: true
|
|
proxy-protocol-version: "2"
|
|
|
|
# Default is 5s, which kills idle websockets/SSE/slow uploads
|
|
idle-connection-timeout: 1h
|
|
|
|
# Auth: public keys only
|
|
authentication: true
|
|
authentication-keys-directory: /pubkeys
|
|
private-keys-directory: /keys
|
|
|
|
# No web UI / consoles
|
|
redirect-root: false
|
|
admin-console: false
|
|
service-console: false
|
|
load-templates: false
|
|
# Default -1 makes the HTTP muxer io.ReadAll() every request/response body into memory
|
|
# (for the console), even with consoles disabled: large uploads OOM-kill sish.
|
|
# 0 = never buffer, stream bodies through.
|
|
service-console-max-content-length: 0
|
|
|
|
log-to-stdout: true
|
|
log-to-file: false
|
|
- path: /etc/containers/systemd/sish.container
|
|
mode: 0644
|
|
contents:
|
|
inline: |
|
|
[Unit]
|
|
Description=sish tunnel server
|
|
|
|
[Container]
|
|
ContainerName=sish
|
|
Image=ghcr.io/antoniomika/sish:v2.24.0
|
|
Network=host
|
|
User=65532
|
|
Group=65532
|
|
DropCapability=all
|
|
AddCapability=CAP_NET_BIND_SERVICE
|
|
NoNewPrivileges=true
|
|
ReadOnly=true
|
|
# sish creates a temp file per forward. The automatic read-only /tmp tmpfs copies the
|
|
# image's /tmp (root, 755), so uid 65532 can't write there: give it a plain sticky /tmp.
|
|
Tmpfs=/tmp:rw,nosuid,nodev,noexec,size=16m,mode=1777,notmpcopyup
|
|
Volume=/etc/sish:/config:ro,Z
|
|
Volume=/var/lib/sish/keys:/keys:ro,Z
|
|
Volume=/var/lib/sish/pubkeys:/pubkeys:ro,Z
|
|
Exec=--config=/config/config.yml
|
|
|
|
[Service]
|
|
Restart=always
|
|
RestartSec=5
|
|
MemoryMax=256M
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
# OS updates: Zincati stages new FCOS releases automatically, this limits the reboot to a window
|
|
- path: /etc/zincati/config.d/55-updates-strategy.toml
|
|
mode: 0644
|
|
contents:
|
|
inline: |
|
|
[updates]
|
|
strategy = "periodic"
|
|
[[updates.periodic.window]]
|
|
days = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
|
|
start_time = "03:00" # UTC
|
|
length_minutes = 60
|
|
# sish updates: no floating tags upstream (only vX.Y.Z), so podman auto-update can't follow a
|
|
# version line. This bumps Image= to the newest tag within TRACK and rolls back if sish
|
|
# doesn't come up again.
|
|
- path: /usr/local/bin/sish-update
|
|
mode: 0755
|
|
contents:
|
|
inline: |
|
|
#!/bin/bash
|
|
set -euo pipefail
|
|
TRACK=v2. # "v2." = minor + patch releases, "v2.24." = patch releases only
|
|
unit=/etc/containers/systemd/sish.container
|
|
repo=ghcr.io/antoniomika/sish
|
|
|
|
current=$(sed -n "s|^Image=$repo:||p" "$unit")
|
|
latest=$(podman search --list-tags --limit 10000 --format '{{.Tag}}' "$repo" \
|
|
| grep -E "^${TRACK//./\\.}[0-9]+(\.[0-9]+)*$" | sort -V | tail -n1)
|
|
if [[ -z $latest || $(printf '%s\n' "$current" "$latest" | sort -V | tail -n1) == "$current" ]]; then
|
|
exit 0
|
|
fi
|
|
|
|
set_image() {
|
|
sed -i "s|^Image=.*|Image=$repo:$1|" "$unit"
|
|
systemctl daemon-reload
|
|
systemctl restart sish.service
|
|
}
|
|
|
|
echo "sish: $current -> $latest"
|
|
podman pull -q "$repo:$latest" >/dev/null
|
|
set_image "$latest"
|
|
sleep 30
|
|
if ! ss -Htln 'sport = :5002' | grep -q .; then
|
|
echo "sish $latest not listening on :5002, rolling back to $current" >&2
|
|
set_image "$current"
|
|
exit 1
|
|
fi
|
|
podman image prune -af >/dev/null
|
|
- path: /etc/sysconfig/nftables.conf
|
|
mode: 0600
|
|
overwrite: true
|
|
contents:
|
|
inline: |
|
|
table inet cirrus
|
|
delete table inet cirrus
|
|
table inet cirrus {
|
|
chain input {
|
|
type filter hook input priority filter; policy drop;
|
|
ct state established,related accept
|
|
ct state invalid drop
|
|
iif "lo" accept
|
|
meta l4proto { icmp, ipv6-icmp } accept
|
|
udp sport 67 udp dport 68 accept
|
|
ip6 saddr fe80::/10 udp sport 547 udp dport 546 accept
|
|
tcp dport { 22, 80, 443, 5001, 5002, 20000-20099 } accept # sish ports: see port-bind-range
|
|
}
|
|
}
|
|
|
|
systemd:
|
|
units:
|
|
- name: sshd-port-selinux.service
|
|
enabled: true
|
|
contents: |
|
|
[Unit]
|
|
Description=Allow sshd to bind 5001/tcp (SELinux)
|
|
Before=sshd.service
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
RemainAfterExit=yes
|
|
ExecCondition=/bin/sh -c '! /usr/sbin/semodule -l | grep -qx sshd_port_5001'
|
|
ExecStart=/usr/sbin/semodule -i /etc/cirrus/sshd_port_5001.cil
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
- name: nftables.service
|
|
enabled: true
|
|
- name: sish-update.service
|
|
contents: |
|
|
[Unit]
|
|
Description=Update sish within its major version
|
|
Wants=network-online.target
|
|
After=network-online.target sish.service
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
ExecStart=/usr/local/bin/sish-update
|
|
- name: sish-update.timer
|
|
enabled: true
|
|
contents: |
|
|
[Unit]
|
|
Description=Daily sish update check
|
|
|
|
[Timer]
|
|
OnCalendar=*-*-* 05:00:00 UTC
|
|
RandomizedDelaySec=30m
|
|
Persistent=true
|
|
|
|
[Install]
|
|
WantedBy=timers.target
|
|
|