me-web? skeleton: Avalonia 12 app, server, packaging and CI
Build / Desktop, server and tools (push) Successful in 1m7s

The first screen (online or not, a Check button, every language with a
draft notice), the desktop and Android heads, the server's /api/info and
/api/ip, a release tool that builds deb, rpm, a Windows exe, macOS zips,
a signed APK and the server, and the Gitea workflows that run it. Rules
adapted from passolo; AGPL-3.0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012CzABvBkbcFqoHdmi8b9WB
This commit is contained in:
thepraandClaude Opus 5.5 committed 2026-10-15 01:14:44 +02:00
commit 7589121846
76 files changed
+3082

No files matched your search

+65
View File
@@ -0,0 +1,65 @@
#!/bin/bash
set -euo pipefail
here="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
site=meweb.arasaka.software
names=(meweb.arasaka.software v4.meweb.arasaka.software v6.meweb.arasaka.software)
app=/var/www/$site
backups=/var/backups/$site
etc=/etc/meweb
env=$etc/meweb.env
unit=/etc/systemd/system/meweb.service
sudoers=/etc/sudoers.d/gitea-runner
acme=/root/.acme.sh/acme.sh
cert=/root/.acme.sh/${site}_ecc/fullchain.cer
[ "$(id -u)" = 0 ] || { echo "run as root"; exit 1; }
id meweb >/dev/null 2>&1 || useradd --system --no-create-home --shell /usr/sbin/nologin meweb
install -d -o gitea-runner -g gitea-runner -m 755 "$app" "$backups"
install -d -o root -g meweb -m 750 "$etc"
if [ ! -f "$env" ]; then
printf '%s\n' \
'ASPNETCORE_ENVIRONMENT=Production' \
'ASPNETCORE_URLS=http://127.0.0.1:5480' \
'DOTNET_PRINT_TELEMETRY_MESSAGE=false' \
'DOTNET_CLI_TELEMETRY_OPTOUT=1' > "$env"
chown root:meweb "$env"
chmod 640 "$env"
echo "wrote $env"
fi
install -m 644 "$here/meweb.service" "$unit"
systemctl daemon-reload
systemctl enable meweb.service >/dev/null 2>&1
line="gitea-runner ALL=(root) NOPASSWD: /usr/bin/systemctl start meweb, /usr/bin/systemctl stop meweb, /usr/bin/systemctl restart meweb, /usr/bin/systemctl is-active meweb, /usr/bin/systemctl show meweb*, /usr/bin/systemctl status meweb*"
if ! grep -qF "$line" "$sudoers"; then
cp "$sudoers" "$sudoers.new"
echo "$line" >> "$sudoers.new"
visudo -cf "$sudoers.new" >/dev/null
install -m 440 "$sudoers.new" "$sudoers"
rm -f "$sudoers.new"
echo "sudoers: meweb added for gitea-runner"
fi
if [ ! -f "$cert" ]; then
install -m 644 "$here/nginx/$site.http.conf" "/etc/nginx/sites-enabled/$site.conf"
nginx -t
systemctl reload nginx
args=()
for name in "${names[@]}"; do args+=(-d "$name"); done
"$acme" --issue --webroot /var/www/acme "${args[@]}" --keylength ec-256 --reloadcmd "systemctl reload nginx"
fi
install -m 644 "$here/nginx/$site.conf" "/etc/nginx/sites-enabled/$site.conf"
nginx -t
systemctl reload nginx
if [ -x "$app/MeWeb.Server" ]; then
systemctl restart meweb
systemctl is-active meweb
else
echo "no build in $app yet: the release workflow deploys it"
fi
echo "setup done"
+24
View File
@@ -0,0 +1,24 @@
[Unit]
Description=me-web? server (meweb.arasaka.software)
After=network-online.target mongod.service
Wants=network-online.target
[Service]
User=meweb
Group=meweb
WorkingDirectory=/var/www/meweb.arasaka.software
ExecStart=/var/www/meweb.arasaka.software/MeWeb.Server
EnvironmentFile=/etc/meweb/meweb.env
Restart=always
RestartSec=5
KillSignal=SIGINT
SyslogIdentifier=meweb
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadOnlyPaths=/var/www/meweb.arasaka.software
MemoryMax=512M
[Install]
WantedBy=multi-user.target
+50
View File
@@ -0,0 +1,50 @@
server {
listen 80;
listen [::]:80;
server_name meweb.arasaka.software v4.meweb.arasaka.software v6.meweb.arasaka.software;
location ^~ /.well-known/acme-challenge/ {
root /var/www/acme;
default_type "text/plain";
allow all;
}
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl;
listen 8444 ssl proxy_protocol;
listen [::]:443 ssl;
server_name meweb.arasaka.software v4.meweb.arasaka.software v6.meweb.arasaka.software;
ssl_certificate /root/.acme.sh/meweb.arasaka.software_ecc/fullchain.cer;
ssl_certificate_key /root/.acme.sh/meweb.arasaka.software_ecc/meweb.arasaka.software.key;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
add_header Referrer-Policy "no-referrer" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "DENY" always;
access_log /var/log/nginx/meweb.arasaka.software.access.log;
error_log /var/log/nginx/meweb.arasaka.software.error.log;
client_max_body_size 128k;
location ^~ /.well-known/acme-challenge/ {
root /var/www/acme;
default_type "text/plain";
allow all;
}
location / {
proxy_pass http://127.0.0.1:5480;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header Connection "";
}
}
@@ -0,0 +1,15 @@
server {
listen 80;
listen [::]:80;
server_name meweb.arasaka.software v4.meweb.arasaka.software v6.meweb.arasaka.software;
location ^~ /.well-known/acme-challenge/ {
root /var/www/acme;
default_type "text/plain";
allow all;
}
location / {
return 301 https://$host$request_uri;
}
}