Deploying Sub-Store on VPS (Docker Compose + Caddy)
- Published on
- ...
- Authors

- Name
- Huashan
- @herohuashan
Sub-Store is an advanced subscription management tool suitable for Loon, Surge, Quantumult X, Shadowrocket, Clash, and other clients. This tutorial will guide you on how to deploy both Caddy and Sub-Store services simultaneously using Docker Compose.
1. Create Complete Docker Compose File
Create a Docker Compose file that includes both Caddy and Sub-Store:
nano docker-compose.yml
Paste the following content:
version: '3.8'
services:
caddy:
image: caddy:latest
container_name: caddy
restart: always
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- caddy_data:/data
- caddy_config:/config
networks:
- app_network
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
sub-store:
image: xream/sub-store:latest
container_name: sub-store
restart: always
volumes:
- sub_store_data:/opt/app/data
environment:
- SUB_STORE_BACKEND_API_PORT=3001
- SUB_STORE_BACKEND_PREFIX=true
- SUB_STORE_FRONTEND_BACKEND_PATH=/sEcUrEpaThExaMpLe98765
expose:
- "3001"
networks:
- app_network
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
networks:
app_network:
driver: bridge
volumes:
caddy_data:
caddy_config:
sub_store_data:
Note:
SUB_STORE_FRONTEND_BACKEND_PATHshould be replaced with a random string for API access security- The above configuration uses a bridge network named
app_network, no external network needed- Caddy container maps ports 80 and 443 to the host, ensure these ports are not occupied
2. Optional Environment Variable Configuration
You can add the following optional environment variables as needed:
environment:
- SUB_STORE_FRONTEND_HOST=0.0.0.0 # Frontend listening address
- SUB_STORE_FRONTEND_PORT=3001 # Frontend listening port
- SUB_STORE_BACKEND_SYNC_CRON=0 0 * * * # Auto-sync subscriptions at 0:00 daily
- SUB_STORE_BACKEND_UPLOAD_CRON=0 1 * * * # Auto-backup config at 1:00 daily
- SUB_STORE_BACKEND_DOWNLOAD_CRON=30 2 * * 0 # Restore config every Sunday at 2:30
- GITHUB_USERNAME=your_github_username_here
- GITHUB_TOKEN=your_github_token_here
# Push service configuration (optional)
- SUB_STORE_PUSH_SERVICE=https://api.day.app/XXX/[Push Title]/[Push Content]?sound=shake
3. Create Caddyfile Configuration
Create the Caddyfile configuration file:
nano Caddyfile
Add the following configuration:
# Sub-Store configuration
sub.yourdomain.com {
reverse_proxy sub-store:3001
encode gzip
header {
# Security headers
Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
X-XSS-Protection "1; mode=block"
X-Content-Type-Options "nosniff"
-Server
}
}
# If you have other services, add them here
# For example:
# n8n.yourdomain.com {
# reverse_proxy n8n:5678
# encode gzip
# }
Please replace sub.yourdomain.com with your actual domain name.
4. Start All Services
Use Docker Compose to start all services:
docker compose up -d
5. Verify Service Running Status
Check if containers are running normally:
docker ps
View service logs:
# View Sub-Store logs
docker logs sub-store
# View Caddy logs
docker logs caddy
6. Reload Caddy Configuration (If Modifying Configuration)
If you need to modify the Caddyfile later, you can reload the configuration after editing:
docker exec -w /etc/caddy caddy caddy reload
7. Access Sub-Store
Access in browser: https://sub.yourdomain.com
Sub-Store API address is: https://sub.yourdomain.com/sEcUrEpaThExaMpLe98765
8. Subscription Link Format
The format for using subscriptions is:
https://sub.yourdomain.com/subs?api=https://sub.yourdomain.com/sEcUrEpaThExaMpLe98765
If using default port and API path, the complete access address is:
https://sub.yourdomain.com/?api=https://sub.yourdomain.com/sEcUrEpaThExaMpLe98765
9. Update Services
When you need to update services, you can use the following commands:
# Pull latest images
docker compose pull
# Update all services
docker compose up -d
# Update only Sub-Store
docker compose up -d --no-deps --build sub-store
# Clean unused images (optional)
docker system prune -f
Security Recommendations
- Ensure your VPS firewall has ports 80 and 443 open
- The value of
SUB_STORE_FRONTEND_BACKEND_PATHshould be randomly generated, don't use simple or default values - Recommend configuring Caddy's HTTPS to ensure secure data transmission
- Security HTTP headers configured enhance access security
- Consider adding access authentication for Sub-Store to prevent unauthorized access
Common Troubleshooting
If you encounter problems, you can check container logs:
docker logs sub-store
Check Caddy logs:
docker logs caddy
If you cannot access, check the following:
- Confirm containers are running normally:
docker ps - Confirm network configuration is correct:
docker network inspect app_network - Confirm firewall has necessary ports open
- Confirm domain DNS is correctly configured to point to your server IP
Comparison with Other Deployment Methods
This tutorial uses Docker Compose to deploy both Caddy and Sub-Store simultaneously, which has the following advantages compared to other methods:
- Integrated Configuration: Manage all related services with one Docker Compose file
- Docker Isolation: Deploying with Docker containers is more secure, avoiding dependency conflicts
- Caddy Auto HTTPS: Caddy automatically applies and renews SSL certificates, no manual configuration needed
- Easy Maintenance: Using Compose files to manage services makes updates and backups simpler
- High Reliability: Container auto-restart policy ensures continuous service operation
- Flexibility: Can easily add more services to the same environment
Advanced Configuration
Add HTTP Basic Authentication for Sub-Store Frontend
If you need to add basic authentication, modify the Caddyfile:
sub.yourdomain.com {
reverse_proxy sub-store:3001
encode gzip
# Basic authentication configuration
basicauth {
username encrypted_password
}
header {
Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
X-XSS-Protection "1; mode=block"
X-Content-Type-Options "nosniff"
-Server
}
}
To generate encrypted password, you can use:
docker exec -it caddy caddy hash-password
Add Multiple Services
If you want to add more services (like RSSHub, N8N, etc.) to the same environment, simply add new service definitions in docker-compose.yml and configure corresponding reverse proxy rules in Caddyfile.
IP Access Restriction
If you need to restrict access to specific IPs only, modify the Caddyfile:
sub.yourdomain.com {
@allowed_ips {
remote_ip 192.168.1.0/24 10.0.0.0/8
}
handle @allowed_ips {
reverse_proxy sub-store:3001
}
handle {
respond "Access denied" 403
}
encode gzip
header {
Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
X-XSS-Protection "1; mode=block"
X-Content-Type-Options "nosniff"
-Server
}
}
Through these steps, you have successfully deployed your own Sub-Store service on VPS and can start enjoying convenient subscription management!
Sub-Store Web Usage Guide
Basic Settings
1. Access Sub-Store Web
Use browser to access your deployed Sub-Store address:
https://sub.yourdomain.com
If using default port and API path, the complete access address is:
https://sub.yourdomain.com/?api=https://sub.yourdomain.com/sEcUrEpaThExaMpLe98765
2. Configure Backend
When first entering the Sub-Store web interface, you need to configure the backend address:
- Click the settings icon in the upper right corner
- Fill in your API address in "Backend Settings":
https://sub.yourdomain.com/sEcUrEpaThExaMpLe98765 - Click "Save"
Add Subscriptions
Sub-Store can manage three types of subscriptions:
1. Add Airport Subscription
- Click "Subscriptions" in the left navigation bar
- Click the "+" button in the lower right corner
- Select "Add Subscription"
- Fill in the form:
- Name: Give the subscription an easily recognizable name
- URL: Paste your airport subscription link
- Type: Select "Subscription"
- Click "Save"
2. Add Personal Node
- After clicking the "+" button, select "Add Node"
- Fill in node information:
- Name: Name the node
- Type: Select protocol type (such as Shadowsocks, VMess, Trojan, etc.)
- Fill in corresponding server information, port, password, etc.
- Click "Save"
3. Create Combined Subscription
- After clicking the "+" button, select "Add Collection"
- Fill in collection information:
- Name: Name the combined subscription
- Select subscriptions or nodes to include
- Click "Save"
Node Management
1. Node Editing and Operations
Select an added subscription and enter the subscription editing page where you can perform the following operations:
Basic Operations
- Filter: Check to enable node filtering
- Sort: Sort nodes by keywords
- Add Flag: Automatically add country/region flags before node names
- UDP Relay: Enable UDP traffic forwarding
- TCP Fast Open: Enable TFO feature
- Skip Certificate Verification: Turn off TLS certificate verification
Node Renaming
Use regular expressions to rename nodes in the format: regex@replacement
For example:
- Remove flags:
Remove flags from node names @ - Add prefix:
(.*)@[NA] $1(add "[NA] " prefix before each node) - Use counter:
.*@Node$count(01)(rename all nodes to "Node01", "Node02", etc.)
2. Use JS Scripts for Advanced Operations
Sub-Store supports using JavaScript scripts for more complex node operations:
- On the subscription editing page, click "Script Operations"
- Select "Local Script" or "Remote Script"
- Fill in script content or URL
- Node rename script:
https://raw.githubusercontent.com/Keywos/rule/refs/heads/main/rename.jsI only use this one - Node alive test script:
https://raw.githubusercontent.com/xream/scripts/main/surge/modules/is-node-alive/index.js - Unlock detection script:
https://raw.githubusercontent.com/Keywos/rule/main/script/notion.js
- Node rename script:
- Parameter settings
- For dlercloud blkey ; iplc+gpt+NF+IPLC+IEPL+[Air]+[Std]+[Pro] name ; dler |
- For TAG blkey ; 1x+2x+3x+5x+10x name ; TAG |
Export Subscriptions
After editing, you can export subscriptions to various formats:
- Click the "Copy" button on the right side of the subscription
- Select target platform (Surge, QX, Clash, etc.)
- Copy the generated subscription link
The generated subscription link format is:
https://sub.yourdomain.com/download/[subscription_name]?target=[platform]
But the rules exported this way don't have routing rules
Use File Management to Create Rules
Sub-Store supports creating complete proxy rule configurations through file management:
1. Surge Rule File
- Click "File Management" on the left
- Click the "+" button to create new file
- Name it:
surge-config.conf - Content example:
[General]
loglevel = notify
bypass-system = true
dns-server = system, 223.5.5.5, 119.29.29.29
skip-proxy = 127.0.0.1, 192.168.0.0/16, 10.0.0.0/8, 172.16.0.0/12, localhost, *.local
[Proxy Group]
Proxy = select, policy-path=https://sub.yourdomain.com/download/MySubscription?target=Surge
[Rule]
RULE-SET,https://raw.githubusercontent.com/DivineEngine/Profiles/master/Surge/Ruleset/Global.list,Proxy
FINAL,DIRECT
Surge config files include node addresses, which won't be shown here
2. Mihomo (Clash Meta) Rule File
- Create new file, name it:
mihomo-config.yaml - Content example:
port: 7890
socks-port: 7891
allow-lan: true
mode: rule
log-level: info
proxies: {}
proxy-providers:
MySubscription:
type: http
url: https://sub.yourdomain.com/download/MySubscription?target=ClashMeta
interval: 3600
path: ./proxies/myprovider.yaml
health-check:
enable: true
interval: 300
url: http://www.gstatic.com/generate_204
proxy-groups:
- name: 🚀 Node Selection
type: select
proxies:
- ♻️ Auto Select
- DIRECT
use:
- MySubscription
- name: ♻️ Auto Select
type: url-test
use:
- MySubscription
url: http://www.gstatic.com/generate_204
interval: 300
rules:
- DOMAIN-SUFFIX,google.com,🚀 Node Selection
- DOMAIN-KEYWORD,google,🚀 Node Selection
- MATCH,DIRECT
Override(JavaScript/YAML) is supported here
You can maintain your own suitable js file here, for example I use my own https://raw.githubusercontent.com/geekhuashan/Substore-rules/refs/heads/main/Mihomo/override.js
3. Sing-box Rule File
- Create new file, name it:
sing-box-config.json - Content example:
{
"dns": {
"servers": [
{
"tag": "dns_proxy",
"address": "https://1.1.1.1/dns-query",
"address_resolver": "dns_resolver",
"strategy": "ipv4_only",
"detour": "proxy"
},
{
"tag": "dns_direct",
"address": "https://223.5.5.5/dns-query",
"address_resolver": "dns_resolver",
"strategy": "ipv4_only",
"detour": "direct"
},
{
"tag": "dns_resolver",
"address": "223.5.5.5",
"strategy": "ipv4_only",
"detour": "direct"
}
],
"rules": [
{
"domain": ["geosite:google"],
"server": "dns_proxy"
}
]
},
"inbounds": [
{
"type": "mixed",
"tag": "mixed-in",
"listen": "::",
"listen_port": 7890
}
],
"outbounds": [
{
"type": "selector",
"tag": "proxy",
"outbounds": ["auto", "all"]
},
{
"type": "urltest",
"tag": "auto",
"outbounds": ["all"],
"url": "https://www.gstatic.com/generate_204",
"interval": "1m"
},
{
"type": "remote",
"tag": "all",
"path": "https://sub.yourdomain.com/download/MySubscription?target=SingBox",
"cache_file": "./cache/remote.json",
"download_detour": "direct"
},
{
"type": "direct",
"tag": "direct"
},
{
"type": "block",
"tag": "block"
},
{
"type": "dns",
"tag": "dns-out"
}
],
"route": {
"rules": [
{
"domain": ["geosite:google"],
"outbound": "proxy"
},
{
"domain_suffix": [".cn"],
"outbound": "direct"
}
]
}
}
Sing-box needs two files, one js to process node information, one json file to define your own routing rules. These are also customized by me, you can find and modify them online. If you don't know how, use Cursor or similar tools for easy vibe coding modifications - that's what I did.
Usage Example: Sub-Store Integration with Mihomo Party
If you use the Mihomo Party client, you can integrate Sub-Store following these steps:
- In Mihomo Party, go to "Subscription Management" > "Sub-Store"
- Click "Add" button
- Enter your Sub-Store backend address:
https://sub.yourdomain.com/sEcUrEpaThExaMpLe98765 - Select the subscription you created from the dropdown menu
- Click "Save"
Now you can directly use Sub-Store managed subscriptions in Mihomo Party.
Advanced Tips
1. Use GitHub to Sync Configuration
Sub-Store supports syncing your configuration via GitHub Gist:
- Create a Personal Access Token on GitHub
- Fill in the Token in Sub-Store's Settings > Sync
- Click "Upload" to create backup
- On other devices, fill in the same Token and click "Download" to restore configuration
2. Scheduled Auto-Sync Subscriptions
In some proxy tools, you can set scheduled tasks to automatically sync your subscriptions:
- Surge: Add scheduled task module
- Quantumult X: Add scheduled task
- Loon: Configure scheduled script
Common Problem Resolution
1. Cannot Access Web Page
- Check if Caddy configuration is correct
- Confirm ports 80 and 443 are open
- Verify domain DNS record correctly points to your server
2. Nodes Not Working
- Check if subscription URL is correct
- Confirm proxy tool correctly imported the subscription
- Verify node information is complete
3. Auto-Sync Failed
- Check GitHub Token permissions are correct
- Confirm there are no network connection issues
- Verify Sub-Store service is running normally
Through this guide, you should be able to fully utilize Sub-Store's powerful features to manage your proxy nodes and subscriptions. For more help, visit Sub-Store's GitHub repository for more information.
Related Posts
Giffgaff UK SIM Card Complete Application Guide
Complete process for applying and activating UK giffgaff eSIM card in China, with practical experience of painlessly unlocking TikTok playback and independently canceling voicemail through UK proxy WiFi Calling.