Deploy: Cloudflare Tunnel + Your Domain & App to appifire-ai-chat.appifire.com
This guide covers:
- Part A: Using Cloudflare Tunnel with your own domain for a stable URL (local dev or exposing a server).
- Part B: Deploying AppiFire AI Chat to https://ai-chat.appifire.com using Dokploy (host) and GitLab (repo + auto deploy), with Cloudflare for DNS.
Production stack: GitLab (source repo) → Dokploy (build & run) → Cloudflare (DNS / optional Tunnel).
Prerequisites: Cloudflare account, domain appifire.com on Cloudflare DNS, GitLab repo with the app code, and a server running Dokploy (or Dokploy cloud).
Part A: Cloudflare Tunnel + Your Domain (Stable URL)
Section titled “Part A: Cloudflare Tunnel + Your Domain (Stable URL)”Cloudflare Tunnel (cloudflared) connects your local machine or server to Cloudflare’s edge. You assign a custom hostname (e.g. appifire-ai-chat.appifire.com) so the URL is stable and no random tunnel subdomain changes.
A.1 When to use this
Section titled “A.1 When to use this”- Local development: Run
shopify app dev(or your Node server) on localhost; expose it athttps://ai-chat.appifire.comso Shopify and post-payment redirects use one stable URL and session cookies work. - Production (optional): Run your app on a VPS and put a Tunnel in front so traffic goes Cloudflare → tunnel → your server (no open ports, DDoS protection).
A.2 Install cloudflared
Section titled “A.2 Install cloudflared”macOS (Homebrew):
brew install cloudflaredWindows (Scoop):
scoop install cloudflaredLinux:
# Debian/Ubuntucurl -L --output cloudflared.deb https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.debsudo dpkg -i cloudflared.debOr download from Cloudflare Tunnel releases.
A.3 Log in and create a tunnel
Section titled “A.3 Log in and create a tunnel”-
Log in (opens browser):
Terminal window cloudflared tunnel loginPick the domain that will host the hostname (e.g.
appifire.com). A certificate file is saved (e.g.~/.cloudflared/<uuid>.json). -
Create a named tunnel (e.g. for local dev):
Terminal window cloudflared tunnel create appifire-ai-chat-devNote the Tunnel ID from the output.
-
Create a config file so the tunnel knows which hostname and local port to use.
Create
~/.cloudflared/config.yml(or a project file, e.g../cloudflared-config.yml):For local development (app running on localhost):
tunnel: <TUNNEL_ID> # from step 2 (e.g. run: cloudflared tunnel list)credentials-file: ~/.cloudflared/<TUNNEL_ID>.jsoningress:- hostname: appifire-ai-chat.appifire.comservice: http://localhost:3000- service: http_status:404Replace
localhost:3000with the port your app uses (e.g. the one fromshopify app dev). One hostname rule is enough; the app serves both HTML and API on the same port.For production (app on a server):
tunnel: <TUNNEL_ID>credentials-file: /path/to/<TUNNEL_ID>.jsoningress:- hostname: appifire-ai-chat.appifire.comservice: http://localhost:3000- service: http_status:404Run
cloudflaredon the same server as the app; pointserviceto the app’s local port.
A.4 Route DNS to the tunnel (Cloudflare)
Section titled “A.4 Route DNS to the tunnel (Cloudflare)”-
In Cloudflare Dashboard → Zero Trust (or Networks → Tunnels), open your tunnel
appifire-ai-chat-dev. -
Go to Public Hostname (or Routes):
- Subdomain:
appifire-ai-chat(so full hostname isappifire-ai-chat.appifire.com). - Domain:
appifire.com. - Service type: HTTP.
- URL:
localhost:3000(or your app’s port).
- Subdomain:
-
Save. Cloudflare will create a CNAME for
appifire-ai-chat.appifire.comto<TUNNEL_ID>.cfargotunnel.com.Or add the CNAME manually in Cloudflare Dashboard → DNS:
- Type: CNAME
- Name:
appifire-ai-chat - Target:
<TUNNEL_ID>.cfargotunnel.com - Proxy status: Proxied (orange cloud) is typical.
A.5 Run the tunnel
Section titled “A.5 Run the tunnel”Local dev:
cloudflared tunnel run appifire-ai-chat-devLeave this running. In another terminal start your app (e.g. cd appifire-ai-chat && shopify app dev). Set in .env:
SHOPIFY_APP_URL=https://ai-chat.appifire.comThen in Shopify Partner Dashboard, set the app URL and redirect URLs to https://ai-chat.appifire.com. You now have a stable URL for local development; post-payment redirects and session cookies will work.
Part B: Deploy App to https://ai-chat.appifire.com (Build + CI/CD)
Section titled “Part B: Deploy App to https://ai-chat.appifire.com (Build + CI/CD)”This section covers building the app, hosting it so it’s reachable at https://ai-chat.appifire.com, and automating deploys with CI/CD. Cloudflare is used for DNS (and optionally Tunnel in front of your host).
B.1 App build and run (summary)
Section titled “B.1 App build and run (summary)”The app is a Node server (React Router). Commands:
| Step | Command |
|---|---|
| Install deps | npm ci |
| Generate Prisma | prisma generate |
| Build | npm run build (react-router build) |
| Migrate DB | prisma migrate deploy |
| Start | npm start (react-router-serve ./build/server/index.js) |
Required env: DATABASE_URL, DIRECT_URL, SHOPIFY_API_KEY, SHOPIFY_API_SECRET, SHOPIFY_APP_URL, SCOPES, OPENROUTER_API_KEY, and any other vars from .env.sample.
B.2 Dokploy: connect GitLab and create the application
Section titled “B.2 Dokploy: connect GitLab and create the application”The app needs Node 20+ and PostgreSQL (with pgvector). Dokploy runs on your server (or Dokploy cloud) and builds/deploys from your GitLab repo.
1. Connect GitLab to Dokploy
- In Dokploy → Git → select GitLab.
- In GitLab: Profile → Applications → Add new application.
- Name: e.g.
Dokploy-Appifire - Redirect URI: copy from Dokploy (e.g.
https://your-dokploy.com/api/providers/gitlab/callback). - Scopes:
api,read_user,read_repository.
- Name: e.g.
- Copy Application ID and Secret from GitLab into Dokploy → Save.
- In Dokploy click Authorize / Install and complete the OAuth flow.
2. Create the Application in Dokploy
- Applications → New Application.
- Source: GitLab → select your repo (e.g.
shopify-ai-chatbotor your group/repo). - Branch:
main(or your production branch). - Root directory:
appifire-ai-chat(if the app lives in a subfolder of the repo). - Build type: Nixpacks (default) or Railpack; Dokploy will detect Node.
- Build command (if configurable):
npm ci && npx prisma generate && npm run build - Start command: Set env var
NIXPACKS_START_CMD(orRAILPACK_START_CMD) to:Or use a Dockerfile inTerminal window npx prisma migrate deploy && npm startappifire-ai-chatif you prefer (see B.5). - Environment variables: Add all vars from B.4 in the application’s Environment tab (e.g.
DATABASE_URL,SHOPIFY_APP_URL,OPENROUTER_API_KEY, etc.). - Port: Expose the port your app listens on (e.g.
3000). Dokploy will map it. - Save and run the first deploy.
3. Postgres (with pgvector) for Dokploy
- Use a Postgres service in Dokploy (Docker Compose or add-on) with the pgvector image (e.g.
pgvector/pgvector:pg15), or use an external Postgres (e.g. your existing Dokploy Postgres instance). SetDATABASE_URLandDIRECT_URLin the app’s env to point to that database.
4. Auto deploy on push (GitLab webhook)
- In Dokploy → your Application → Deployments tab → Add Webhook; copy the webhook URL.
- In GitLab → your repo → Settings → Webhooks:
- URL: paste the Dokploy webhook URL.
- Trigger: Push events (and optionally tag push if you use tags).
- Push to the configured branch (e.g.
main) will trigger a new build and deploy in Dokploy.
B.3 Pointing appifire-ai-chat.appifire.com at Dokploy (Cloudflare DNS)
Section titled “B.3 Pointing appifire-ai-chat.appifire.com at Dokploy (Cloudflare DNS)”- In Dokploy, your application gets a URL (e.g.
appifire-ai-chat.your-server.comor a port-based URL). Add a custom domain in the app settings if Dokploy supports it:appifire-ai-chat.appifire.com. - In Cloudflare Dashboard → DNS for
appifire.com:- Type: CNAME
- Name:
appifire-ai-chat - Target: the Dokploy app URL (e.g. your server hostname or the URL Dokploy shows for the app).
- Proxy status: Proxied (orange) for CDN/DDoS, or DNS only if Dokploy handles SSL.
- Wait for SSL and test:
curl -I https://ai-chat.appifire.com.
Alternative: Cloudflare Tunnel in front of Dokploy server
If the app runs on a server behind Dokploy and you don’t want to expose the server directly:
- On the same server (or a reachable host), run cloudflared with a tunnel and public hostname
appifire-ai-chat.appifire.com→http://localhost:<app-port>(the port Dokploy maps for the app). - In Cloudflare DNS, set CNAME
appifire-ai-chat→<TUNNEL_ID>.cfargotunnel.com. Traffic goes Cloudflare → Tunnel → your app.
B.4 Environment variables in Dokploy
Section titled “B.4 Environment variables in Dokploy”Set these (and any others from .env.sample) in Dokploy → your Application → Environment:
| Variable | Example / note |
|---|---|
NODE_ENV | production |
SHOPIFY_API_KEY | From Partner Dashboard |
SHOPIFY_API_SECRET | From Partner Dashboard |
SHOPIFY_APP_URL | https://ai-chat.appifire.com |
SCOPES | Same as in shopify.app.toml (comma-separated) |
DATABASE_URL | Postgres connection string (pooled if applicable) |
DIRECT_URL | Postgres direct connection (for migrations) |
OPENROUTER_API_KEY | From OpenRouter |
EMBEDDING_MARKUP_FACTOR | e.g. 2.0 |
CHAT_MARKUP_FACTOR | e.g. 2.0 |
LLM_MODEL_FREE | e.g. google/gemma-2-9b-it:free |
LLM_MODEL_PAID | e.g. openai/gpt-4o-mini |
Migrations run on start via the start command (npx prisma migrate deploy && npm start).
B.5 Build process (Dokploy + optional Dockerfile)
Section titled “B.5 Build process (Dokploy + optional Dockerfile)”Nixpacks / Railpack (default): Dokploy runs install, generate, and build from your build command; start runs migrations + npm start from the env var above.
Optional: Dockerfile in appifire-ai-chat
If you prefer a Docker build, add appifire-ai-chat/Dockerfile:
FROM node:20-alpine AS builderWORKDIR /appCOPY package*.json ./RUN npm ciCOPY . .RUN npx prisma generate && npm run build
FROM node:20-alpineWORKDIR /appCOPY --from=builder /app/node_modules ./node_modulesCOPY --from=builder /app/build ./buildCOPY --from=builder /app/package*.json ./COPY --from=builder /app/prisma ./prismaEXPOSE 3000CMD ["sh", "-c", "npx prisma migrate deploy && npm start"]In Dokploy, set Build type to Dockerfile and point to this Dockerfile. No need to set NIXPACKS_START_CMD.
B.6 GitLab CI/CD (optional pipeline + Dokploy webhook)
Section titled “B.6 GitLab CI/CD (optional pipeline + Dokploy webhook)”Deploy via webhook (recommended): Pushing to main triggers the GitLab webhook you added in B.2; Dokploy pulls the repo and rebuilds/redeploys. No GitLab CI file required.
Optional: GitLab CI for test + notify
To run tests or lint before deploy, or to trigger Dokploy via API after a successful pipeline, add .gitlab-ci.yml in the repo root:
stages: - test - deploy
variables: APP_PATH: appifire-ai-chat NODE_VERSION: "20"
test: stage: test image: node:${NODE_VERSION}-alpine before_script: - cd $APP_PATH - npm ci - npx prisma generate script: - npm run build # - npm run lint # - npm test # add if you have tests only: - main
# Optional: trigger Dokploy redeploy via API after tests pass# Uncomment and set DOKPLOY_URL + DOKPLOY_TOKEN in GitLab CI/CD variables# deploy:# stage: deploy# image: curlimages/curl:latest# script:# - curl -X POST "${DOKPLOY_URL}/api/applications/${APP_ID}/deploy" -H "Authorization: Bearer ${DOKPLOY_TOKEN}"# only:# - main# when: on_success- Secrets: In GitLab → Settings → CI/CD → Variables, add
DATABASE_URL(andDOKPLOY_URL/DOKPLOY_TOKENif you use the deploy job). Mark sensitive vars as Masked. - If you rely on the webhook only, every push to
mainalready deploys; the CI job above just adds a test gate. To deploy only when CI passes, you can use a branch protection rule that requires pipeline success, and keep the webhook onmain.
B.7 Shopify Partner Dashboard
Section titled “B.7 Shopify Partner Dashboard”After the app is live at https://ai-chat.appifire.com:
- App URL:
https://ai-chat.appifire.com - Allowed redirection URL(s):
https://ai-chat.appifire.com/auth/callback,
https://ai-chat.appifire.com/auth/session-token,
and any other auth paths your stack uses. - In
shopify.app.toml, setapplication_url(and any URL config) tohttps://ai-chat.appifire.com.
Then run shopify app deploy when you change the theme app extension or config.
B.8 Theme extension and public API
Section titled “B.8 Theme extension and public API”- Theme App Extension: Deploy with
shopify app deploy. The widget’sapiUrl(or equivalent) in the extension config should behttps://ai-chat.appifire.comso the storefront calls your production API. - Public API: Endpoints like
/api/widget-settingsand/api/chatare served by the same Node app; no extra Cloudflare config beyond DNS (and optional Tunnel) above.
Checklist
Section titled “Checklist”Part A – Stable URL (local or server):
-
cloudflaredinstalled and logged in - Tunnel created and config has hostname
appifire-ai-chat.appifire.comand correctserviceport - Cloudflare DNS: CNAME
appifire-ai-chat→<TUNNEL_ID>.cfargotunnel.com -
cloudflared tunnel run <name>running when using the URL -
.envand Shopify app URL set tohttps://ai-chat.appifire.com
Part B – Production (Dokploy + GitLab) at appifire-ai-chat.appifire.com:
- GitLab repo connected to Dokploy; Application created with branch
mainand rootappifire-ai-chat - Build and start commands (or Dockerfile) set; env vars (including
DATABASE_URL,SHOPIFY_APP_URL) set in Dokploy - Postgres with pgvector available;
DATABASE_URL/DIRECT_URLpoint to it - GitLab webhook added (Push events) so push to
maintriggers Dokploy deploy - Cloudflare DNS:
appifire-ai-chatCNAME to Dokploy app URL (or Tunnel) - Optional:
.gitlab-ci.ymladded for test stage; CI/CD variables set - Partner Dashboard and extension point to
https://ai-chat.appifire.com