> ## Documentation Index
> Fetch the complete documentation index at: https://docs.aspfox.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Deploy to Railway

> Step-by-step: deploy the AspFox API and frontend to Railway with managed PostgreSQL and Redis.

Railway is the fastest path to production. It manages PostgreSQL and Redis as plugins, and deploys from your GitHub repository automatically on every push.

<Steps>
  <Step title="Create a Railway account and project">
    1. Go to [railway.app](https://railway.app) and sign up
    2. Click **New Project**
    3. Select **Empty Project**
    4. Name the project (e.g., `Acme Production`)
  </Step>

  <Step title="Add PostgreSQL">
    1. In your project, click **New** → **Database** → **Add PostgreSQL**
    2. Railway creates a PostgreSQL instance and adds it to your project
    3. Click on the PostgreSQL service → **Variables** tab
    4. Copy the `DATABASE_URL` value — you will need it shortly
  </Step>

  <Step title="Add Redis">
    1. Click **New** → **Database** → **Add Redis**
    2. Click on the Redis service → **Variables** tab
    3. Copy the `REDIS_URL` value
  </Step>

  <Step title="Deploy the API">
    1. Click **New** → **GitHub Repo**
    2. Connect your GitHub account and select your repository
    3. Railway detects the `Dockerfile` in the project root and uses it
    4. Before the first deploy, go to the service's **Variables** tab
    5. Add all required environment variables (see [Environment Variables](/configuration/environment-variables)):

    ```bash theme={null}
    ASPNETCORE_ENVIRONMENT=Production
    DATABASE_URL=<copied from PostgreSQL plugin>
    REDIS_URL=<copied from Redis plugin>
    JWT_PRIVATE_KEY=<base64 private key — generate new for production>
    JWT_PUBLIC_KEY=<base64 public key>
    JWT_ISSUER=https://api.yourdomain.com
    JWT_AUDIENCE=https://yourdomain.com
    STRIPE_SECRET_KEY=sk_live_…
    STRIPE_WEBHOOK_SECRET=whsec_…  (set this after registering the webhook)
    STRIPE_PRO_PRICE_ID=price_…
    STRIPE_BUSINESS_PRICE_ID=price_…
    RESEND_API_KEY=re_…
    EMAIL_FROM_ADDRESS=noreply@yourdomain.com
    EMAIL_FROM_NAME=Acme
    APP_URL=https://yourdomain.com
    API_URL=https://api.yourdomain.com
    ```

    6. Click **Deploy** — Railway builds the Docker image and starts the container
  </Step>

  <Step title="Run migrations">
    1. Install the Railway CLI: `npm install -g @railway/cli`
    2. Log in: `railway login`
    3. Link your project: `railway link`
    4. Run migrations against the production database:

    ```bash theme={null}
    railway run -- dotnet ef database update \
      --project src/Acme.Infrastructure \
      --startup-project src/Acme.Api
    ```

    Or open a shell in the running container and run the migration:

    ```bash theme={null}
    railway shell
    dotnet ef database update \
      --project src/Acme.Infrastructure \
      --startup-project src/Acme.Api
    ```
  </Step>

  <Step title="Run the database seeder">
    ```bash theme={null}
    railway shell
    dotnet run --project src/Acme.Api -- --seed-only
    ```

    This creates the admin user. The `--seed-only` flag runs seeders and exits without starting the HTTP server.
  </Step>

  <Step title="Deploy the frontend">
    1. In your Railway project, click **New** → **GitHub Repo** again
    2. Select the same repository, but this time set the **Root Directory** to `frontend/`
    3. Add the frontend environment variable:

    ```bash theme={null}
    VITE_API_URL=https://api.yourdomain.com
    ```

    4. Railway detects `package.json` and uses the Vite build command (`npm run build`)
    5. Set the **Start Command** to `npx serve -s dist -l 3000`
  </Step>

  <Step title="Configure custom domains">
    1. For the API service: **Settings** → **Domains** → **Generate Domain** or **Add Custom Domain**
    2. Add a CNAME record in your DNS pointing `api.yourdomain.com` to the Railway-provided domain
    3. Repeat for the frontend service at `yourdomain.com` or `app.yourdomain.com`
    4. Railway provisions SSL automatically via Let's Encrypt
  </Step>

  <Step title="Register the Stripe webhook">
    Now that you have a production API URL:

    1. Stripe Dashboard → **Developers → Webhooks** → **Add endpoint**
    2. URL: `https://api.yourdomain.com/api/v1/webhooks/stripe`
    3. Select all five required events (checkout.session.completed, customer.subscription.updated, customer.subscription.deleted, invoice.payment\_failed, invoice.payment\_succeeded)
    4. Copy the signing secret → update `STRIPE_WEBHOOK_SECRET` in Railway

    Railway redeploys automatically when you update environment variables.
  </Step>

  <Step title="Verify">
    1. Open `https://yourdomain.com` — the login page should load
    2. Log in with admin credentials (email set via `--AdminEmail` at scaffold time, password `Admin123!`)
    3. Change the admin password immediately
    4. Test a complete checkout with a real payment method
    5. Confirm the Stripe webhook delivered successfully in the Stripe Dashboard
  </Step>
</Steps>

<Warning>
  After verifying everything works, change the default admin password from `Admin123!` to something secure. Do this before announcing the application publicly.
</Warning>
