Restructure repository to manage both server2 and caddy-vps
Deploy / security (push) Failing after 11m14s
Deploy / lint (push) Failing after 12m3s
Deploy / deploy (push) Has been skipped

- Create server2/ directory and migrate Xray proxy config, Clash config, and utility scripts
- Create caddy-vps/ directory and add Caddyfile reverse proxy configuration
- Update .gitea/workflows/deploy.yml CI/CD pipeline to validate JSON/YAML and check Caddyfile formatting/syntax
- Deploy configurations sequentially to both servers
- Update README.md to document multi-server topology and CI/CD behavior

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Gan, Jimmy
2026-06-03 03:19:18 +08:00
parent 55a8dbc457
commit 4a91c7a186
11 changed files with 158 additions and 66 deletions
+23 -8
View File
@@ -14,10 +14,18 @@ jobs:
run: | run: |
git clone http://gitea:3000/jimmy/vps-oracle-jp.git . git clone http://gitea:3000/jimmy/vps-oracle-jp.git .
git checkout ${{ github.sha }} git checkout ${{ github.sha }}
- name: Validate JSON - name: Validate JSON (Xray)
run: python3 -c "import json; json.load(open('xray-config.json'))" run: python3 -c "import json; json.load(open('server2/xray-config.json'))"
- name: Validate YAML - name: Validate YAML (Clash Meta)
run: pip install pyyaml -q --break-system-packages && python3 -c "import yaml; yaml.safe_load(open('clash-meta.yaml'))" run: pip install pyyaml -q --break-system-packages && python3 -c "import yaml; yaml.safe_load(open('server2/clash-meta.yaml'))"
- name: Install Caddy for validation
run: |
curl -L -o caddy "https://caddyserver.com/api/download?os=linux&arch=amd64"
chmod +x caddy
- name: Validate Caddyfile formatting
run: ./caddy fmt --check caddy-vps/Caddyfile
- name: Validate Caddyfile syntax
run: ./caddy validate --config caddy-vps/Caddyfile --adapter caddyfile
security: security:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -32,7 +40,7 @@ jobs:
- name: Check for secrets - name: Check for secrets
run: | run: |
FOUND=0 FOUND=0
if grep -rE '-----BEGIN (RSA |EC |OPENSSH )?PRIVATE KEY-----' --include='*.json' --include='*.yaml' --include='*.yml' --include='*.md' .; then if grep -rE '-----BEGIN (RSA |EC |OPENSSH )?PRIVATE KEY-----' --include='*.json' --include='*.yaml' --include='*.yml' --include='*.md' --include='Caddyfile' .; then
echo "ERROR: Private key found in repo" echo "ERROR: Private key found in repo"
FOUND=1 FOUND=1
fi fi
@@ -49,7 +57,7 @@ jobs:
run: | run: |
git clone http://gitea:3000/jimmy/vps-oracle-jp.git . git clone http://gitea:3000/jimmy/vps-oracle-jp.git .
git checkout ${{ github.sha }} git checkout ${{ github.sha }}
- name: Deploy xray config - name: Setup SSH
env: env:
VPS_SSH_KEY: ${{ secrets.VPS_SSH_KEY }} VPS_SSH_KEY: ${{ secrets.VPS_SSH_KEY }}
run: | run: |
@@ -57,5 +65,12 @@ jobs:
echo "$VPS_SSH_KEY" > ~/.ssh/id_ed25519 echo "$VPS_SSH_KEY" > ~/.ssh/id_ed25519
chmod 600 ~/.ssh/id_ed25519 chmod 600 ~/.ssh/id_ed25519
ssh-keyscan -H 158.101.140.85 >> ~/.ssh/known_hosts 2>/dev/null ssh-keyscan -H 158.101.140.85 >> ~/.ssh/known_hosts 2>/dev/null
scp xray-config.json jimmyg@158.101.140.85:/tmp/xray-config.json ssh-keyscan -H 161.33.182.109 >> ~/.ssh/known_hosts 2>/dev/null
ssh jimmyg@158.101.140.85 "sudo cp /tmp/xray-config.json /usr/local/etc/xray/config.json && sudo chmod 644 /usr/local/etc/xray/config.json && sudo systemctl restart xray" - name: Deploy Xray config to server2
run: |
scp server2/xray-config.json jimmyg@158.101.140.85:/tmp/xray-config.json
ssh jimmyg@158.101.140.85 "sudo cp /tmp/xray-config.json /usr/local/etc/xray/config.json && sudo chmod 600 /usr/local/etc/xray/config.json && sudo systemctl restart xray"
- name: Deploy Caddy config to caddy-vps
run: |
scp caddy-vps/Caddyfile ubuntu@161.33.182.109:/tmp/Caddyfile
ssh ubuntu@161.33.182.109 "sudo cp /tmp/Caddyfile /etc/caddy/Caddyfile && sudo chmod 644 /etc/caddy/Caddyfile && sudo systemctl reload caddy"
+55 -58
View File
@@ -1,65 +1,62 @@
# VPS Oracle Japan - Proxy Server # VPS Infrastructure Management - Oracle Japan
> CI/CD last tested: 2026-02-18
## Server Info Multi-server infrastructure configuration and deployment rules for Tokyo VPS instances.
- IP: 158.101.140.85
- OS: Ubuntu 24.04 LTS
- SSH: `ssh server2`
## VLESS + Reality (Xray) ---
- Protocol: VLESS
- Port: 443
- UUID: 7bb711be-47a2-4273-aa8e-45bcb6216f70
- Flow: xtls-rprx-vision
- Security: reality
- SNI: www.microsoft.com
- Public Key: 203MXpq2G45goHJB7gmdEorwORVeyBOvEISlcLCrWms
- Private Key: *(stored on server only — see `/usr/local/etc/xray/config.json`)*
- Short ID: abcd1234
- Fingerprint: safari
### Client URI ## 🖥️ Server Registry
```
vless://7bb711be-47a2-4273-aa8e-45bcb6216f70@158.101.140.85:443?encryption=none&flow=xtls-rprx-vision&security=reality&sni=www.microsoft.com&fp=safari&pbk=203MXpq2G45goHJB7gmdEorwORVeyBOvEISlcLCrWms&sid=abcd1234&type=tcp#Japan-VPS ### 1. `server2` (Tokyo Region)
* **Public IP**: `158.101.140.85`
* **Tailscale IP**: `100.70.115.1` (`oracle-tokyo`)
* **Role**: Fast Outbound Network Proxy & Network-level AdGuard DNS resolver.
* **SSH Access**: `ssh server2` (uses user `jimmyg`, key `~/.ssh/id_ed25519_vps`)
* **Running Services**:
* **Xray**: VLESS+Reality protocol on port `443`.
* **Tailscale**: Active exit node to route external mesh network traffic.
* **WireGuard**: Client tunnel on port `51820`.
* **AdGuard Home**: Network-wide ad blocker and local resolver on DNS port `53` and Web UI port `3000` (Tailscale bound).
* **fail2ban**: Brute-force mitigation active for SSH.
### 2. `caddy-vps` (Tokyo Region)
* **Public IP**: `161.33.182.109`
* **Tailscale IP**: `100.109.198.126` (`caddy-proxy`)
* **Role**: Public edge reverse proxy with HTTPS (Let's Encrypt TLS) and Authelia forward-auth integration.
* **SSH Access**: `ssh caddy-vps` (uses user `ubuntu`, key `~/.ssh/id_ed25519_vps`)
* **Running Services**:
* **Caddy**: Edge web server listening on ports `80` and `443` to route traffic to local Synology NAS services.
* **Tailscale**: Node agent to connect to local NAS services on the mesh network.
---
## 📁 Repository Structure
```text
vps-oracle-jp/
├── server2/ # Configurations & tools for server2
│ ├── xray-config.json # VLESS+Reality server proxy config
│ ├── clash-meta.yaml # Clash Meta mobile configuration
│ ├── japan-vps-qr.png # Shadowrocket client setup QR
│ ├── clash-meta-qr.png # Clash Meta client setup QR
│ ├── harden.sh # Server security hardening script
│ ├── setup-tailscale-exit-node.sh # Exit node router config script
│ └── uptime-check.sh # Server service health check utility
├── caddy-vps/ # Configurations for caddy-vps
│ └── Caddyfile # Active reverse proxy routing rules
└── .gitea/
└── workflows/deploy.yml # Automated multi-server CI/CD pipeline
``` ```
## Tailscale ---
- VPS: 100.70.115.1 (oracle-tokyo, exit node enabled)
- NAS: 100.78.131.124 (ds224plus)
- Phone: 100.83.55.44 (huawei-mate-70)
- iPhone: 100.111.7.83 (iphone181)
- Mac: 100.65.185.12 (macbook-air)
## Files ## 🚀 CI/CD Automated Deployment
- `xray-config.json` — Xray server config (deployed to `/usr/local/etc/xray/config.json`) Deployments are managed automatically on Gitea via Gitea Actions whenever changes are pushed to the `main` branch:
- `clash-meta.yaml` — Clash Meta client config for Android
- `japan-vps-qr.png` — Shadowrocket QR code
- `clash-meta-qr.png` — Clash Meta QR code
## AdGuard Home 1. **Validation & Linting**:
- Web UI: http://100.70.115.1:3000 (Tailscale only) * Tests `server2/xray-config.json` for proper JSON syntax.
- DNS: 100.70.115.1:53 * Tests `server2/clash-meta.yaml` for correct YAML structural formatting.
- Login: admin / *(change default password!)* * Downloads a static Caddy binary to format check (`caddy fmt --check`) and syntax validate (`caddy validate --adapter caddyfile`) the `caddy-vps/Caddyfile`.
- Tailscale DNS: set 100.70.115.1 as nameserver at https://login.tailscale.com/admin/dns 2. **Security Scan**:
- **IMPORTANT**: In Tailscale admin DNS settings, enable "Use with exit node" for this nameserver * Verifies that no private keys or high-risk credentials have been accidentally committed to any text files in the repository.
and "Override DNS servers" to bypass GFW DNS poisoning 3. **SSH Deployments**:
* Deploys `xray-config.json` to `/usr/local/etc/xray/config.json` on `server2`, sets strict permissions (`600`), and restarts Xray.
## Exit Node Setup Notes * Deploys `Caddyfile` to `/etc/caddy/Caddyfile` on `caddy-vps`, sets safe permissions (`644`), and performs a zero-downtime `systemctl reload caddy`.
- UFW forward policy must be `ACCEPT` (in `/etc/default/ufw`)
- NAT MASQUERADE rule for `ens3` added to `/etc/ufw/before.rules`
- Without these, Tailscale exit node traffic is silently dropped
## Services Running
- Xray (VLESS+Reality) on port 443
- Tailscale (exit node)
- WireGuard on port 51820
- AdGuard Home (DNS ad blocker)
- fail2ban (SSH protection)
## Security
- SSH: key-only auth, root login disabled
- UFW: only 22/tcp, 443/tcp (iptables), 51820/udp open
- fail2ban: active
- Old Clash Meta proxy: stopped and disabled
- nginx: stopped and disabled
- rpcbind: disabled
+80
View File
@@ -0,0 +1,80 @@
(security_headers) {
header {
X-Content-Type-Options nosniff
X-Frame-Options SAMEORIGIN
Referrer-Policy strict-origin-when-cross-origin
X-XSS-Protection "1; mode=block"
-Server
}
}
(authelia) {
forward_auth 100.78.131.124:9092 {
uri /api/verify?rd=https://auth.jimmygan.com
copy_headers Remote-User Remote-Groups Remote-Name Remote-Email
}
}
# Authelia portal (no forward_auth on itself)
auth.jimmygan.com {
import security_headers
reverse_proxy 100.78.131.124:9092
}
# Protected services
nas.jimmygan.com {
import security_headers
import authelia
reverse_proxy 100.78.131.124:4000 {
header_up Host {host}
header_up X-Real-IP {remote_host}
header_up X-Forwarded-For {remote_host}
header_up X-Forwarded-Proto {scheme}
header_up X-Forwarded-Host {host}
}
}
dev.nas.jimmygan.com {
import security_headers
import authelia
reverse_proxy 100.78.131.124:4001
}
music.jimmygan.com {
import security_headers
import authelia
reverse_proxy 100.78.131.124:4533 {
flush_interval -1
}
}
photos.jimmygan.com {
import security_headers
import authelia
reverse_proxy 100.78.131.124:2283 {
header_up X-Forwarded-Proto https
header_up X-Forwarded-Host {host}
transport http {
read_timeout 10m
write_timeout 10m
}
}
}
photos-app.jimmygan.com {
import security_headers
reverse_proxy 100.78.131.124:2283 {
header_up X-Forwarded-Proto https
header_up X-Forwarded-Host {host}
transport http {
read_timeout 10m
write_timeout 10m
}
}
}
git.jimmygan.com {
import security_headers
import authelia
reverse_proxy 100.78.131.124:3300
}

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB