Skip to content

Deploy: Cloudflare Tunnel + Your Domain & App to appifire-ai-chat.appifire.com

This guide covers:

  1. Part A: Using Cloudflare Tunnel with your own domain for a stable URL (local dev or exposing a server).
  2. 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.

  • Local development: Run shopify app dev (or your Node server) on localhost; expose it at https://ai-chat.appifire.com so 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).

macOS (Homebrew):

Terminal window
brew install cloudflared

Windows (Scoop):

Terminal window
scoop install cloudflared

Linux:

Terminal window
# Debian/Ubuntu
curl -L --output cloudflared.deb https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb
sudo dpkg -i cloudflared.deb

Or download from Cloudflare Tunnel releases.

  1. Log in (opens browser):

    Terminal window
    cloudflared tunnel login

    Pick the domain that will host the hostname (e.g. appifire.com). A certificate file is saved (e.g. ~/.cloudflared/<uuid>.json).

  2. Create a named tunnel (e.g. for local dev):

    Terminal window
    cloudflared tunnel create appifire-ai-chat-dev

    Note the Tunnel ID from the output.

  3. 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>.json
    ingress:
    - hostname: appifire-ai-chat.appifire.com
    service: http://localhost:3000
    - service: http_status:404

    Replace localhost:3000 with the port your app uses (e.g. the one from shopify 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>.json
    ingress:
    - hostname: appifire-ai-chat.appifire.com
    service: http://localhost:3000
    - service: http_status:404

    Run cloudflared on the same server as the app; point service to the app’s local port.

  1. In Cloudflare DashboardZero Trust (or NetworksTunnels), open your tunnel appifire-ai-chat-dev.

  2. Go to Public Hostname (or Routes):

    • Subdomain: appifire-ai-chat (so full hostname is appifire-ai-chat.appifire.com).
    • Domain: appifire.com.
    • Service type: HTTP.
    • URL: localhost:3000 (or your app’s port).
  3. Save. Cloudflare will create a CNAME for appifire-ai-chat.appifire.com to <TUNNEL_ID>.cfargotunnel.com.

    Or add the CNAME manually in Cloudflare DashboardDNS:

    • Type: CNAME
    • Name: appifire-ai-chat
    • Target: <TUNNEL_ID>.cfargotunnel.com
    • Proxy status: Proxied (orange cloud) is typical.

Local dev:

Terminal window
cloudflared tunnel run appifire-ai-chat-dev

Leave 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.com

Then 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.


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).

The app is a Node server (React Router). Commands:

StepCommand
Install depsnpm ci
Generate Prismaprisma generate
Buildnpm run build (react-router build)
Migrate DBprisma migrate deploy
Startnpm 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

  1. In DokployGit → select GitLab.
  2. In GitLab: Profile → ApplicationsAdd 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.
  3. Copy Application ID and Secret from GitLab into Dokploy → Save.
  4. In Dokploy click Authorize / Install and complete the OAuth flow.

2. Create the Application in Dokploy

  1. ApplicationsNew Application.
  2. Source: GitLab → select your repo (e.g. shopify-ai-chatbot or your group/repo).
  3. Branch: main (or your production branch).
  4. Root directory: appifire-ai-chat (if the app lives in a subfolder of the repo).
  5. Build type: Nixpacks (default) or Railpack; Dokploy will detect Node.
  6. Build command (if configurable): npm ci && npx prisma generate && npm run build
  7. Start command: Set env var NIXPACKS_START_CMD (or RAILPACK_START_CMD) to:
    Terminal window
    npx prisma migrate deploy && npm start
    Or use a Dockerfile in appifire-ai-chat if you prefer (see B.5).
  8. 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.).
  9. Port: Expose the port your app listens on (e.g. 3000). Dokploy will map it.
  10. 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). Set DATABASE_URL and DIRECT_URL in the app’s env to point to that database.

4. Auto deploy on push (GitLab webhook)

  1. In Dokploy → your Application → Deployments tab → Add Webhook; copy the webhook URL.
  2. In GitLab → your repo → SettingsWebhooks:
    • URL: paste the Dokploy webhook URL.
    • Trigger: Push events (and optionally tag push if you use tags).
  3. 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)”
  1. In Dokploy, your application gets a URL (e.g. appifire-ai-chat.your-server.com or a port-based URL). Add a custom domain in the app settings if Dokploy supports it: appifire-ai-chat.appifire.com.
  2. In Cloudflare DashboardDNS 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.
  3. 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:

  1. On the same server (or a reachable host), run cloudflared with a tunnel and public hostname appifire-ai-chat.appifire.comhttp://localhost:<app-port> (the port Dokploy maps for the app).
  2. In Cloudflare DNS, set CNAME appifire-ai-chat<TUNNEL_ID>.cfargotunnel.com. Traffic goes Cloudflare → Tunnel → your app.

Set these (and any others from .env.sample) in Dokploy → your Application → Environment:

VariableExample / note
NODE_ENVproduction
SHOPIFY_API_KEYFrom Partner Dashboard
SHOPIFY_API_SECRETFrom Partner Dashboard
SHOPIFY_APP_URLhttps://ai-chat.appifire.com
SCOPESSame as in shopify.app.toml (comma-separated)
DATABASE_URLPostgres connection string (pooled if applicable)
DIRECT_URLPostgres direct connection (for migrations)
OPENROUTER_API_KEYFrom OpenRouter
EMBEDDING_MARKUP_FACTORe.g. 2.0
CHAT_MARKUP_FACTORe.g. 2.0
LLM_MODEL_FREEe.g. google/gemma-2-9b-it:free
LLM_MODEL_PAIDe.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 builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npx prisma generate && npm run build
FROM node:20-alpine
WORKDIR /app
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/build ./build
COPY --from=builder /app/package*.json ./
COPY --from=builder /app/prisma ./prisma
EXPOSE 3000
CMD ["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 → SettingsCI/CDVariables, add DATABASE_URL (and DOKPLOY_URL / DOKPLOY_TOKEN if you use the deploy job). Mark sensitive vars as Masked.
  • If you rely on the webhook only, every push to main already 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 on main.

After the app is live at https://ai-chat.appifire.com:

  1. App URL: https://ai-chat.appifire.com
  2. 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.
  3. In shopify.app.toml, set application_url (and any URL config) to https://ai-chat.appifire.com.

Then run shopify app deploy when you change the theme app extension or config.

  • Theme App Extension: Deploy with shopify app deploy. The widget’s apiUrl (or equivalent) in the extension config should be https://ai-chat.appifire.com so the storefront calls your production API.
  • Public API: Endpoints like /api/widget-settings and /api/chat are served by the same Node app; no extra Cloudflare config beyond DNS (and optional Tunnel) above.

Part A – Stable URL (local or server):

  • cloudflared installed and logged in
  • Tunnel created and config has hostname appifire-ai-chat.appifire.com and correct service port
  • Cloudflare DNS: CNAME appifire-ai-chat<TUNNEL_ID>.cfargotunnel.com
  • cloudflared tunnel run <name> running when using the URL
  • .env and Shopify app URL set to https://ai-chat.appifire.com

Part B – Production (Dokploy + GitLab) at appifire-ai-chat.appifire.com:

  • GitLab repo connected to Dokploy; Application created with branch main and root appifire-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_URL point to it
  • GitLab webhook added (Push events) so push to main triggers Dokploy deploy
  • Cloudflare DNS: appifire-ai-chat CNAME to Dokploy app URL (or Tunnel)
  • Optional: .gitlab-ci.yml added for test stage; CI/CD variables set
  • Partner Dashboard and extension point to https://ai-chat.appifire.com