-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcloud-config.yaml
More file actions
231 lines (191 loc) · 7.42 KB
/
cloud-config.yaml
File metadata and controls
231 lines (191 loc) · 7.42 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
#cloud-config
# Hetzner Cloud VPS setup for Yak Shears
# References:
# - https://community.hetzner.com/tutorials/basic-cloud-config
# - https://cloudinit.readthedocs.io/en/latest/reference/examples.html
#
# ⚠️ REQUIRED: Replace placeholders before deployment
#
# CHECKLIST:
# [ ] <public_ssh_key> - Full SSH public key from ~/.ssh/id_ed25519.pub
# [ ] yak-shears.kyleking.me - Your domain (in Caddyfile section)
# [ ] dev.act.kyle+caddy@gmail.com - Your email for Let's Encrypt
# [ ] Review passwordless sudo (see DEPLOYMENT.md Security Notes)
# SECURITY NOTE: This configuration grants passwordless sudo for convenience.
# For production, consider restricting to specific commands. See DEPLOYMENT.md.
users:
- name: yakshears
groups: users, admin
sudo: ALL=(ALL) NOPASSWD:ALL # ⚠️ See security note above
shell: /bin/bash
ssh_authorized_keys:
- <public_ssh_key> # ⚠️ REPLACE with your SSH public key
packages:
- fail2ban
- ufw
- git
- curl
- gnupg2
- apt-transport-https
- debian-keyring
- debian-archive-keyring
package_update: true
package_upgrade: true
write_files:
# SSH hardening configuration (drop-in file for sshd_config)
- path: /etc/ssh/sshd_config.d/99-ssh-hardening.conf
content: |
# SSH hardening for yak-shears deployment
PermitRootLogin no
PasswordAuthentication no
Port 2222
KbdInteractiveAuthentication no
ChallengeResponseAuthentication no
MaxAuthTries 2
AllowTcpForwarding no
X11Forwarding no
AllowAgentForwarding no
AuthorizedKeysFile .ssh/authorized_keys
AllowUsers yakshears
# Yak Shears systemd service
- path: /etc/systemd/system/yak-shears.service
content: |
[Unit]
Description=Yak Shears Server
After=network.target
[Service]
User=yakshears
WorkingDirectory=/home/yakshears/yak-shears
ExecStart=/home/yakshears/.local/bin/uv run --no-sync serve
Restart=always
RestartSec=10
Environment=YAK_SHEARS_DIR=/home/yakshears/Sync/yak-shears
[Install]
WantedBy=multi-user.target
# GitOps update script
- path: /usr/local/bin/gitops-update.sh
permissions: '0755'
content: |
#!/bin/bash
set -euo pipefail
cd /home/yakshears/yak-shears || exit 1
# Fetch latest changes
git fetch origin main || exit 1
LOCAL=$(git rev-parse HEAD)
REMOTE=$(git rev-parse origin/main)
if [ "$LOCAL" != "$REMOTE" ]; then
echo "Updates detected. Pulling changes..."
git pull origin main || exit 1
echo "Installing dependencies..."
/home/yakshears/.local/bin/mise install || exit 1
/home/yakshears/.local/bin/uv sync || exit 1
echo "Restarting service..."
systemctl restart yak-shears || exit 1
echo "Update completed successfully"
else
echo "No updates available"
fi
# GitOps systemd service
- path: /etc/systemd/system/gitops-update.service
content: |
[Unit]
Description=Check for git updates and restart if needed
[Service]
Type=oneshot
User=yakshears
ExecStart=/usr/local/bin/gitops-update.sh
StandardOutput=journal
StandardError=journal
# GitOps systemd timer (runs every 5 minutes)
- path: /etc/systemd/system/gitops-update.timer
content: |
[Unit]
Description=Run GitOps update every 5 minutes
[Timer]
OnBootSec=5min
OnUnitActiveSec=5min
Persistent=true
[Install]
WantedBy=timers.target
# Caddy reverse proxy configuration
- path: /etc/caddy/Caddyfile
content: |
{
email dev.act.kyle+caddy@gmail.com # REPLACE with your email for Let's Encrypt
}
yak-shears.kyleking.me { # REPLACE with your domain
reverse_proxy localhost:8084 {
header_up Host {host}
header_up X-Real-IP {remote_host}
header_up X-Forwarded-For {remote_host}
header_up X-Forwarded-Proto {scheme}
}
# Security headers
header {
Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
X-Content-Type-Options "nosniff"
X-Frame-Options "DENY"
Referrer-Policy "same-origin"
X-XSS-Protection "1; mode=block"
Permissions-Policy "geolocation=(), microphone=(), camera=()"
}
# Logging
log {
output file /var/log/caddy/yak-shears.log
}
}
runcmd:
# Configure fail2ban for SSH protection
- printf "[sshd]\nenabled = true\nport = ssh, 2222\nbanaction = iptables-multiport" > /etc/fail2ban/jail.local || exit 1
- systemctl enable fail2ban || exit 1
- systemctl start fail2ban || exit 1
# Configure UFW firewall
- ufw allow 2222/tcp || exit 1 # SSH
- ufw allow http/tcp || exit 1 # HTTP (for ACME challenge)
- ufw allow https/tcp || exit 1 # HTTPS
- ufw allow 22000/tcp || exit 1 # Syncthing data
- ufw allow 22000/udp || exit 1 # Syncthing data
- ufw allow 21027/udp || exit 1 # Syncthing discovery
- ufw --force enable || exit 1
# Update package lists
- apt update || exit 1
# Install uv (Python package manager)
- sudo -u yakshears sh -c 'curl -LsSf https://astral.sh/uv/install.sh | sh' || exit 1
# Install mise (tool version manager)
- sudo -u yakshears sh -c 'curl -fsSL https://mise.jdx.dev/install.sh | sh' || exit 1
# Install Syncthing
- mkdir -p /etc/apt/keyrings || exit 1
- curl -L -o /etc/apt/keyrings/syncthing-archive-keyring.gpg https://syncthing.net/release-key.gpg || exit 1
- echo "deb [signed-by=/etc/apt/keyrings/syncthing-archive-keyring.gpg] https://apt.syncthing.net/ syncthing stable" | tee /etc/apt/sources.list.d/syncthing.list || exit 1
- apt update || exit 1
- apt install -y syncthing || exit 1
# Install Caddy
- curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg || exit 1
- curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | tee /etc/apt/sources.list.d/caddy-stable.list || exit 1
- apt update || exit 1
- apt install -y caddy || exit 1
# Setup Yak Shears directories
- mkdir -p /home/yakshears/Sync/yak-shears || exit 1
- chown -R yakshears:yakshears /home/yakshears/Sync || exit 1
# Clone repository and install dependencies
# NOTE: For private repos, add SSH deploy key to GitHub and update URL to git@github.com:...
- sudo -u yakshears git clone https://github.com/KyleKing/yak-shears.git /home/yakshears/yak-shears || exit 1
- sudo -u yakshears sh -c 'cd /home/yakshears/yak-shears && /home/yakshears/.local/bin/mise install' || exit 1
- sudo -u yakshears sh -c 'cd /home/yakshears/yak-shears && /home/yakshears/.local/bin/uv sync' || exit 1
# Enable and start Syncthing
- systemctl enable syncthing@yakshears.service || exit 1
- systemctl start syncthing@yakshears.service || exit 1
# Enable and start Caddy
- systemctl enable caddy || exit 1
- systemctl start caddy || exit 1
# Enable and start Yak Shears
- systemctl enable yak-shears || exit 1
- systemctl start yak-shears || exit 1
# Setup GitOps timer
- systemctl daemon-reload || exit 1
- systemctl enable gitops-update.timer || exit 1
- systemctl start gitops-update.timer || exit 1
# Restart SSH to apply hardened config
- systemctl restart sshd || exit 1
# Reboot to ensure clean state
- sleep 10 && reboot