Restructure repository to manage both server2 and caddy-vps
- 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:
@@ -14,10 +14,18 @@ jobs:
|
||||
run: |
|
||||
git clone http://gitea:3000/jimmy/vps-oracle-jp.git .
|
||||
git checkout ${{ github.sha }}
|
||||
- name: Validate JSON
|
||||
run: python3 -c "import json; json.load(open('xray-config.json'))"
|
||||
- name: Validate YAML
|
||||
run: pip install pyyaml -q --break-system-packages && python3 -c "import yaml; yaml.safe_load(open('clash-meta.yaml'))"
|
||||
- name: Validate JSON (Xray)
|
||||
run: python3 -c "import json; json.load(open('server2/xray-config.json'))"
|
||||
- name: Validate YAML (Clash Meta)
|
||||
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:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -32,7 +40,7 @@ jobs:
|
||||
- name: Check for secrets
|
||||
run: |
|
||||
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"
|
||||
FOUND=1
|
||||
fi
|
||||
@@ -49,7 +57,7 @@ jobs:
|
||||
run: |
|
||||
git clone http://gitea:3000/jimmy/vps-oracle-jp.git .
|
||||
git checkout ${{ github.sha }}
|
||||
- name: Deploy xray config
|
||||
- name: Setup SSH
|
||||
env:
|
||||
VPS_SSH_KEY: ${{ secrets.VPS_SSH_KEY }}
|
||||
run: |
|
||||
@@ -57,5 +65,12 @@ jobs:
|
||||
echo "$VPS_SSH_KEY" > ~/.ssh/id_ed25519
|
||||
chmod 600 ~/.ssh/id_ed25519
|
||||
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 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"
|
||||
ssh-keyscan -H 161.33.182.109 >> ~/.ssh/known_hosts 2>/dev/null
|
||||
- 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"
|
||||
|
||||
@@ -1,65 +1,62 @@
|
||||
# VPS Oracle Japan - Proxy Server
|
||||
> CI/CD last tested: 2026-02-18
|
||||
# VPS Infrastructure Management - Oracle Japan
|
||||
|
||||
## Server Info
|
||||
- IP: 158.101.140.85
|
||||
- OS: Ubuntu 24.04 LTS
|
||||
- SSH: `ssh server2`
|
||||
Multi-server infrastructure configuration and deployment rules for Tokyo VPS instances.
|
||||
|
||||
## 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
|
||||
```
|
||||
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
|
||||
## 🖥️ Server Registry
|
||||
|
||||
### 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
|
||||
- `xray-config.json` — Xray server config (deployed to `/usr/local/etc/xray/config.json`)
|
||||
- `clash-meta.yaml` — Clash Meta client config for Android
|
||||
- `japan-vps-qr.png` — Shadowrocket QR code
|
||||
- `clash-meta-qr.png` — Clash Meta QR code
|
||||
## 🚀 CI/CD Automated Deployment
|
||||
Deployments are managed automatically on Gitea via Gitea Actions whenever changes are pushed to the `main` branch:
|
||||
|
||||
## AdGuard Home
|
||||
- Web UI: http://100.70.115.1:3000 (Tailscale only)
|
||||
- DNS: 100.70.115.1:53
|
||||
- Login: admin / *(change default password!)*
|
||||
- Tailscale DNS: set 100.70.115.1 as nameserver at https://login.tailscale.com/admin/dns
|
||||
- **IMPORTANT**: In Tailscale admin DNS settings, enable "Use with exit node" for this nameserver
|
||||
and "Override DNS servers" to bypass GFW DNS poisoning
|
||||
|
||||
## Exit Node Setup Notes
|
||||
- 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
|
||||
1. **Validation & Linting**:
|
||||
* Tests `server2/xray-config.json` for proper JSON syntax.
|
||||
* Tests `server2/clash-meta.yaml` for correct YAML structural formatting.
|
||||
* Downloads a static Caddy binary to format check (`caddy fmt --check`) and syntax validate (`caddy validate --adapter caddyfile`) the `caddy-vps/Caddyfile`.
|
||||
2. **Security Scan**:
|
||||
* Verifies that no private keys or high-risk credentials have been accidentally committed to any text files in the repository.
|
||||
3. **SSH Deployments**:
|
||||
* Deploys `xray-config.json` to `/usr/local/etc/xray/config.json` on `server2`, sets strict permissions (`600`), and restarts Xray.
|
||||
* Deploys `Caddyfile` to `/etc/caddy/Caddyfile` on `caddy-vps`, sets safe permissions (`644`), and performs a zero-downtime `systemctl reload caddy`.
|
||||
|
||||
@@ -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 |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
Reference in New Issue
Block a user