# style **Repository Path**: ldlx/style ## Basic Information - **Project Name**: style - **Description**: 海外 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-02-04 - **Last Updated**: 2026-02-15 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # style-service Two FastAPI apps with a Celery worker for async image stylization using a third-party API and Cloudflare R2. ## Services - `client-api`: device login, templates, file presign, task submit, task status - `admin`: user and config management (starter CRUD) - `worker`: async task submission and polling ## Quick start (dev) 1. Copy `.env.example` to `.env` and fill values (MySQL DSN by default). 2. Start Redis and MySQL: - `docker-compose up -d` 3. (Optional) Initialize MySQL users/db: - `mysql -h 127.0.0.1 -u root -p < mysql-init.sql` 4. Run apps: - `uvicorn apps.client.main:app --reload --port 8000` - uvicorn apps.client.main:app --reload --host 0.0.0.0 --port 8000 - `uvicorn apps.admin.main:app --reload --port 8001` - celery -A worker.celery_app worker --loglevel=info - `celery -A worker.celery_app.celery_app worker --loglevel=info` 5. Run DB migrations (Alembic): - `alembic upgrade head` ## Admin UI (Vue 3 + TS) 1. `cd admin-ui` 2. `cp .env.example .env` (optional) 3. `npm install` 4. `npm run dev` ## Notes - R2 presigned upload returns a URL and key. Client should upload directly to R2. - Third-party API is async with HTTP callback. - Callback signature verification uses HMAC-SHA256 of raw request body. - Client tokens are stored in Redis with TTL (single-session per device). - Admin login uses `/admin/login` with `username/password`, then pass `X-Admin-Token`. - Alembic template file is required at `alembic/script.py.mako` for autogenerate. - Migration workflow: - alembic heads - alembic merge 20260204_05 c48691d46e63 -m "merge heads" 1. Apply latest migrations: `alembic upgrade head` 2. Generate a new migration after model changes: `alembic revision --autogenerate -m "update schema"` ## Deployment checklist (prod) - Environment & secrets - Set production `.env` values (DB/Redis/R2/TP/ADMIN/CLIENT_PUBLIC_BASE_URL). - Rotate and store all secrets (DB password, R2 keys, TP keys) in a secret manager if possible. - Set `APP_ENV=prod`, `AUTO_CREATE_TABLES=false`. - Database - Provision MySQL with backups and restricted user. - Run migrations: `alembic upgrade head`. - Verify schema on boot (tables exist, no pending migrations). - Redis - Provision Redis with auth and persistence. - Ensure `REDIS_URL` is reachable from app/worker. - R2 storage - R2 bucket CORS: allow your admin UI domain for `PUT/GET/HEAD/POST`. - Public access: enable Public bucket **or** use a custom domain (recommended). - If using custom domain (e.g., `cdn.pixforge.top`), set `R2_PUBLIC_BASE_URL` to that domain and wait for domain status to be Active. - Third‑party API - Verify `TP_BASE_URL`, `TP_SUBMIT_PATH`, `TP_STATUS_PATH`, `TP_TIMEOUT_SECONDS`. - Confirm callback secret matches vendor (if callbacks are used). - Networking & TLS - Put `client-api` and `admin` behind Nginx/Caddy/Traefik. - Enable HTTPS and set correct `CLIENT_PUBLIC_BASE_URL` (must be public HTTPS for callbacks). - Configure CORS on admin API if admin UI is on a separate domain. - Process management - Run `client-api`, `admin`, and `worker` with systemd/supervisor/pm2 (or Docker). - Set log rotation and health checks. - Frontend (admin-ui) - Build: `npm run build`. - Serve static files with Nginx and point API base to admin API. - Security - Change `ADMIN_USERNAME/ADMIN_PASSWORD`. - Restrict admin API by IP allowlist if possible. - Observability - Add error logging (Sentry or similar). - Monitor worker queue depth and task failures. - Final smoke tests - Device login works and returns token. - Presign + upload to R2 works. - Task submit → worker → result URL works. - Admin CRUD works (templates, configs, users). ## Deployment runbook (Ubuntu 22.04 + Docker) > Replace domains/paths/credentials with your own. ### 1) Server prep ```bash apt update && apt upgrade -y apt install -y curl git ufw # Optional: set timezone timedatectl set-timezone Asia/Hong_Kong # Basic firewall ufw allow 22/tcp ufw allow 80/tcp ufw allow 443/tcp ufw enable ``` ### 2) Install Docker + Compose ```bash curl -fsSL https://get.docker.com | sh systemctl enable docker && systemctl start docker # Install docker compose plugin apt install -y docker-compose-plugin ``` ### 3) Clone and configure ```bash mkdir -p /srv cd /srv git clone style cd style # Create .env cp .env.example .env # Edit .env with production values ``` Key `.env` items: - `DATABASE_URL` (MySQL) - `REDIS_URL` - `R2_*` (endpoint/keys/bucket/public url) - `TP_*` (third-party API) - `ADMIN_USERNAME` / `ADMIN_PASSWORD` - `CLIENT_PUBLIC_BASE_URL` (https://api.yourdomain.com) ### 4) Start infra (MySQL + Redis) ```bash docker compose up -d ``` ### 5) Migrate DB ```bash source .venv/bin/activate # or use your venv alembic upgrade head ``` ### 6) Run services (systemd) Create systemd units (examples): `/etc/systemd/system/style-client.service` ```ini [Unit] Description=style client api After=network.target [Service] WorkingDirectory=/srv/style EnvironmentFile=/srv/style/.env ExecStart=/srv/style/.venv/bin/uvicorn apps.client.main:app --host 0.0.0.0 --port 8000 Restart=always [Install] WantedBy=multi-user.target ``` `/etc/systemd/system/style-admin.service` ```ini [Unit] Description=style admin api After=network.target [Service] WorkingDirectory=/srv/style EnvironmentFile=/srv/style/.env ExecStart=/srv/style/.venv/bin/uvicorn apps.admin.main:app --host 0.0.0.0 --port 8001 Restart=always [Install] WantedBy=multi-user.target ``` `/etc/systemd/system/style-worker.service` ```ini [Unit] Description=style worker After=network.target [Service] WorkingDirectory=/srv/style EnvironmentFile=/srv/style/.env ExecStart=/srv/style/.venv/bin/celery -A worker.celery_app worker --loglevel=info --concurrency=2 Restart=always [Install] WantedBy=multi-user.target ``` Enable and start: ```bash systemctl daemon-reload systemctl enable style-client style-admin style-worker systemctl start style-client style-admin style-worker ``` ### 7) Build Admin UI ```bash cd /srv/style/admin-ui npm install npm run build ``` ### 8) Nginx + HTTPS Install Nginx + certbot: ```bash apt install -y nginx certbot python3-certbot-nginx ``` Example Nginx: ``` server { listen 80; server_name api.pixforge.top; location / { proxy_pass http://127.0.0.1:8000; } } server { listen 80; server_name admin.pixforge.top; location / { proxy_pass http://127.0.0.1:8001; } } server { listen 80; server_name panel.pixforge.top; root /srv/style/admin-ui/dist; index index.html; location / { try_files $uri /index.html; } } ``` Enable HTTPS: ```bash certbot --nginx -d api.pixforge.top -d admin.pixforge.top -d panel.pixforge.top ``` Notes: - Disable the default site to avoid the nginx welcome page: - `rm -f /etc/nginx/sites-enabled/default` - If you use Cloudflare, switch DNS records to **DNS only** before running certbot, then switch back after HTTPS is issued. ### 9) Post‑deploy checklist - Rotate secrets (R2/API/admin passwords) - Verify uploads to R2 + public access - Verify Celery is consuming tasks - Check logs: `journalctl -u style-client -f` ## Code update (after you change code) ### If you used git clone ```bash cd /srv/style git pull # If you changed Python deps source /srv/style/.venv/bin/activate pip install -r requirements.txt # If you changed DB models alembic upgrade head # Restart services systemctl restart style-client systemctl restart style-admin systemctl restart style-worker ``` ## Launch checklist (before promotion) - Rotate all secrets (R2 keys, admin password, API keys). - Ensure `CLIENT_PUBLIC_BASE_URL` is HTTPS and reachable. - Verify HTTPS certificates for `api/admin/panel`. - Switch Cloudflare records to **Proxied** if desired and confirm no 520/522. - Confirm R2 CORS is limited to your real admin/UI domains. - Confirm MySQL is **not** publicly exposed (use SSH tunnel only). - Verify worker is consuming tasks and queue is healthy. - Run a full upload → task → result test in production. ### If you re-uploaded the folder (scp/rsync) ```bash cd /srv/style # If you changed Python deps source /srv/style/.venv/bin/activate pip install -r requirements.txt # If you changed DB models alembic upgrade head # Rebuild admin UI cd /srv/style/admin-ui npm install npm run build # Restart services systemctl restart style-client systemctl restart style-admin systemctl restart style-worker ```