Skip to content

Add domain management commands to Railway CLI#968

Open
m-abdelwahab wants to merge 5 commits into
masterfrom
mahmoud/domain-management-commands
Open

Add domain management commands to Railway CLI#968
m-abdelwahab wants to merge 5 commits into
masterfrom
mahmoud/domain-management-commands

Conversation

@m-abdelwahab

@m-abdelwahab m-abdelwahab commented Jun 14, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds a Domain Management MVP to the Railway CLI and local MCP server. Users and agents can now create, list, inspect, update, retry certificates for, and delete Railway service domains and custom domains from the CLI.

What Changed

  • Added domain subcommands:
    • railway domain list / ls
    • railway domain status <domain-or-id>
    • railway domain update <domain-or-id>
    • railway domain certificate retry <domain-or-id>
    • railway domain delete <domain-or-id> / remove / rm
  • Extended existing railway domain [DOMAIN] create behavior with --port.
  • Added service-domain target port updates and service-domain rename support.
  • Added custom-domain target port updates.
  • Added custom-domain certificate retry support.
  • Added local MCP parity for create/list/status/update/certificate retry/delete domain workflows.
  • Preserved legacy railway domain --json output shapes.
  • Fixed custom-domain creation with CLI OAuth by removing the standalone customDomainAvailable preflight and relying on customDomainCreate, matching dashboard behavior.

CLI Commands

railway domain [DOMAIN] [--port <PORT>] [--service <SERVICE>] [--environment <ENVIRONMENT>] [--project <PROJECT_ID>] [--json]
railway domain list [--service <SERVICE>] [--environment <ENVIRONMENT>] [--project <PROJECT_ID>] [--json]
railway domain status <DOMAIN_OR_ID> [--service <SERVICE>] [--environment <ENVIRONMENT>] [--project <PROJECT_ID>] [--json]
railway domain update <DOMAIN_OR_ID> [--port <PORT>] [--domain <DOMAIN_OR_LABEL>] [--service <SERVICE>] [--environment <ENVIRONMENT>] [--project <PROJECT_ID>] [--json]
railway domain certificate retry <DOMAIN_OR_ID> [--service <SERVICE>] [--environment <ENVIRONMENT>] [--project <PROJECT_ID>] [--json]
railway domain delete <DOMAIN_OR_ID> [--yes] [--service <SERVICE>] [--environment <ENVIRONMENT>] [--project <PROJECT_ID>] [--json]

Notes:

  • <DOMAIN_OR_ID> accepts a domain ID, domain name, or full URL.
  • --port must be in the range 1-65535.
  • --domain renames Railway-provided service domains only. Custom domains cannot be renamed.
  • domain certificate retry supports custom domains only.
  • --yes makes deletion non-interactive.

JSON Output Contracts

Legacy create/list behavior remains compatible:

{ "domain": "https://example.up.railway.app" }
{ "domains": ["https://example.up.railway.app"] }

railway domain list --json:

{
  "domains": [
    {
      "id": "0240ae9b-453b-4885-abcc-30c79ecdaab1",
      "domain": "example.up.railway.app",
      "type": "service",
      "targetPort": 8080,
      "syncStatus": "ACTIVE",
      "createdAt": "2026-06-14T13:01:36.312+00:00",
      "updatedAt": "2026-06-14T13:01:36.866+00:00"
    }
  ]
}

railway domain status --json, railway domain update --json, and railway domain certificate retry --json:

{
  "domain": {
    "id": "c310f34c-0276-4eba-a6fa-9c85e07fe518",
    "domain": "custom.example.com",
    "type": "custom",
    "targetPort": 8080,
    "syncStatus": "ACTIVE",
    "createdAt": "2026-06-14T13:00:14.183+00:00",
    "updatedAt": "2026-06-14T13:00:49.926+00:00",
    "dnsRecords": [
      {
        "recordType": "DNS_RECORD_TYPE_CNAME",
        "name": "custom",
        "fqdn": "custom.example.com",
        "requiredValue": "example.up.railway.app",
        "currentValue": "",
        "status": "DNS_RECORD_STATUS_REQUIRES_UPDATE",
        "zone": "example.com",
        "purpose": "DNS_RECORD_PURPOSE_TRAFFIC_ROUTE"
      }
    ],
    "verification": {
      "verified": false,
      "dnsHost": "_railway-verify.custom",
      "token": "railway-verify=..."
    },
    "certificate": {
      "status": "CERTIFICATE_STATUS_TYPE_VALIDATING_OWNERSHIP"
    }
  }
}

railway domain delete --json:

{
  "deleted": true,
  "domain": {
    "id": "c310f34c-0276-4eba-a6fa-9c85e07fe518",
    "domain": "custom.example.com",
    "type": "custom",
    "targetPort": 8080,
    "syncStatus": "ACTIVE",
    "createdAt": "2026-06-14T13:00:14.183+00:00",
    "updatedAt": "2026-06-14T13:00:49.926+00:00"
  }
}

Custom-domain creation keeps the existing mutation-shaped output:

{
  "customDomainCreate": {
    "id": "c310f34c-0276-4eba-a6fa-9c85e07fe518",
    "domain": "custom.example.com",
    "targetPort": 3000,
    "syncStatus": "CREATING",
    "status": {
      "dnsRecords": [],
      "certificateStatus": "CERTIFICATE_STATUS_TYPE_VALIDATING_OWNERSHIP",
      "verified": false
    }
  }
}

MCP Tools

  • generate_domain
  • list_domains
  • domain_status
  • update_domain
  • retry_domain_certificate
  • delete_domain

Notes

  • Dashboard domain management uses direct domain mutations, not the environment patch flow. This PR matches that API flow.
  • TCP proxies still use the environment patch flow in the dashboard; domains do not.
  • Certificate retry uses the dashboard/internal customDomainIssueCertificate mutation with token auth.
  • Service-domain creation now passes targetPort directly to serviceDomainCreate, avoiding create-then-update sync races.
  • Custom-domain creation now matches the dashboard mutation path, which avoids the CLI OAuth failure caused by calling the standalone availability query.

Testing

  • cargo build --quiet
  • cargo test --quiet
    • 322 passed
  • git diff --check

Live Smoke Test

Ran a full end-to-end smoke test against a new Railway project:

  • Created and deployed a Node service.
  • Verified deployment reached SUCCESS.
  • Created/listed/inspected/updated/renamed/deleted a service domain.
  • Verified service-domain live routing moved from port 3000 to 8080.
  • Created/listed/inspected/updated/deleted a custom domain.
  • Verified custom-domain DNS, certificate, and verification output.
  • Created a disposable custom domain, retried certificate issuance by ID, verified service-domain retry is rejected, then deleted the disposable custom domain.
  • Recreated a final service domain and verified legacy JSON output remains compatible.

Final smoke project was intentionally left running for inspection.

@m-abdelwahab m-abdelwahab added the release/minor Author minor release label Jun 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

release/minor Author minor release

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant