@n8n-as-code/skills 2.1.0-next.44 → 2.1.0-next.45

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  {
2
- "generatedAt": "2026-05-11T07:23:47.232Z",
2
+ "generatedAt": "2026-05-11T08:14:21.198Z",
3
3
  "n8nVersion": "unknown",
4
4
  "sourceFileCount": 428,
5
5
  "scanDirectories": [
@@ -1,5 +1,5 @@
1
1
  {
2
- "generatedAt": "2026-05-11T07:23:48.060Z",
2
+ "generatedAt": "2026-05-11T08:14:22.065Z",
3
3
  "version": "1.0.0",
4
4
  "sourceUrl": "https://docs.n8n.io/llms.txt",
5
5
  "totalPages": 1278,
@@ -17580,13 +17580,13 @@
17580
17580
  "nodeName": null,
17581
17581
  "nodeType": null,
17582
17582
  "content": {
17583
- "markdown": "# Hosting n8n on Google Cloud Run\n\nThis hosting guide shows you how to self-host n8n on Google Cloud Run, a serverless container runtime. If you're just getting started with n8n and don't need a production-grade deployment, you can go with the \"easy mode\" option below for deployment. Otherwise, if you intend to use this n8n deployment at-scale, refer to the \"durable mode\" instructions further down.\n\nYou can also enable access via OAuth to Google Workspace, such as Gmail and Drive, to use these services as n8n workflow tools. Instructions for granting n8n access to these services are at the end of of this documentation.\n\nIf you want to deploy to Google Kubernetes Engine (GKE) instead, you can refer to [these instructions](../google-kubernetes-engine/).\n\nSelf-hosting knowledge prerequisites\n\nSelf-hosting n8n requires technical knowledge, including:\n\n- Setting up and configuring servers and containers\n- Managing application resources and scaling\n- Securing servers and applications\n- Configuring n8n\n\nn8n recommends self-hosting for expert users. Mistakes can lead to data loss, security issues, and downtime. If you aren't experienced at managing servers, n8n recommends [n8n Cloud](https://n8n.io/cloud/).\n\nStable and Beta versions\n\nn8n releases a new minor version most weeks. The `stable` version is for production use. `beta` is the most recent release. The `beta` version may be unstable. To report issues, use the [forum](https://community.n8n.io/c/questions/12).\n\nCurrent `stable`: 2.19.5 Current `beta`: 2.20.5\n\n## Before you begin: get a Google Cloud project\n\nIf you have not yet created a Google Cloud project, [do this first](https://developers.google.com/workspace/guides/create-project) (and ensure you have billing enabled on the project; even if your Cloud Run service runs for free you must have billing activated to deploy). Otherwise, navigate to the project where you want to deploy n8n.\n\n## Easy mode\n\nThis is the fastest way to deploy n8n on Cloud Run. For this deployment, n8n's data is in-memory so this is only recommended for demo purposes. **Anytime this Cloud Run service scales to zero or is redeployed, the n8n data will be lost.** Refer to the durable mode instructions below if you need a production-grade deployment.\n\nIf you have not yet created a Google Cloud project, [do this first](https://developers.google.com/workspace/guides/create-project) (and ensure you have billing enabled on the project; even if your Cloud Run service will run for free you must have billing enabled to activated to deploy). Otherwise, navigate to the project where you want to deploy n8n.\n\nOpen the Cloud Shell Terminal (on the Google Cloud console, either type \"G\" then \"S\" or click on the terminal icon on the upper right).\n\nOnce your session is open, you may need to run this command first to login (and follow the steps it asks you to complete):\n\n```\ngcloud auth login\n```\n\nYou can also explicitly enable the Cloud Run API (even if you don't do this, it will ask if you want this enabled when you deploy):\n\n```\ngcloud services enable run.googleapis.com\n```\n\nRequired: Custom health check endpoint\n\nGoogle Cloud Run reserves `/healthz` for its own health checks. Since n8n uses this path by default, it can conflict and cause connection issues in the workflow canvas. To fix this, set the `N8N_ENDPOINT_HEALTH` environment variable to a custom path (included in the deployment commands below).\n\nTo deploy n8n:\n\n```\ngcloud run deploy n8n \\\n --image=n8nio/n8n \\\n --region=us-west1 \\\n --allow-unauthenticated \\\n --port=5678 \\\n --no-cpu-throttling \\\n --memory=2Gi \\\n --set-env-vars=\"N8N_ENDPOINT_HEALTH=health\"\n```\n\n(you can specify whichever region you prefer, instead of \"us-west1\")\n\nOnce the deployment finishes, open another tab to navigate to the Service URL. n8n may still be loading and you will see a \"n8n is starting up. Please wait\" message, but shortly thereafter you should see the n8n login screen.\n\nOptional: If you want to keep this n8n service running for as long as possible to avoid data loss, you can also set manual scale to 1 to prevent it from autoscaling to 0.\n\n```\ngcloud run deploy n8n \\\n --image=n8nio/n8n \\\n --region=us-west1 \\\n --allow-unauthenticated \\\n --port=5678 \\\n --no-cpu-throttling \\\n --memory=2Gi \\\n --scaling=1 \\\n --set-env-vars=\"N8N_ENDPOINT_HEALTH=health\"\n```\n\nThis does not prevent data loss completely, such as whenever the Cloud Run service is re-deployed/updated. If you want truly persistant data, you should refer to the instructions below for how to attach a database.\n\n## Durable mode\n\nThe following instructions are intended for a more durable, production-grade deployment of n8n on Cloud Run. It includes resources such as a database for persistance and secret manager for sensitive data.\n\nIf you want to deploy the following setup via Terraform, refer to this [example](https://github.com/ryanpei/n8n-hosting/tree/main/google-cloud-run) which deploys the same setup as the following (without the OAuth setup for Google Workspace tools).\n\n## Enable APIs and set env vars\n\nOpen the Cloud Shell Terminal (on the Google Cloud console, either type \"G\" then \"S\" or click on the terminal icon on the upper right) and run these commands in the terminal session:\n\n```\n## You may need to login first\ngcloud auth login\n\ngcloud services enable run.googleapis.com\ngcloud services enable sqladmin.googleapis.com\ngcloud services enable secretmanager.googleapis.com\n```\n\nYou'll also want to set some environment variables for the remainder of these instructions:\n\n```\nexport PROJECT_ID=your-project\nexport REGION=region-where-you-want-this-deployed\n```\n\n## Setup your Postgres database\n\nRun this command to create the Postgres DB instance (it will take a few minutes to complete; also ensure you update the root-password field with your own desired password):\n\n```\ngcloud sql instances create n8n-db \\\n --database-version=POSTGRES_13 \\\n --tier=db-f1-micro \\\n --region=$REGION \\\n --root-password=\"change-this-password\" \\\n --storage-size=10GB \\\n --availability-type=ZONAL \\\n --no-backup \\\n --storage-type=HDD\n```\n\nOnce complete, you can add the database that n8n will use:\n\n```\ngcloud sql databases create n8n --instance=n8n-db\n```\n\nCreate the DB user for n8n (change the password value, of course):\n\n```\ngcloud sql users create n8n-user \\\n --instance=n8n-db \\\n --password=\"change-this-password\"\n```\n\nYou can save the password you set for this n8n-user to a file for the next step of saving the password in Secret Manager. Be sure to delete this file later.\n\n## Store sensitive data in Secret Manager\n\nWhile not required, it's absolutely recommended to store your sensitive data in Secrets Manager.\n\nCreate a secret for the database password (replace \"/your/password/file\" with the file you created above for the n8n-user password):\n\n```\ngcloud secrets create n8n-db-password \\\n --data-file=/your/password/file \\\n --replication-policy=\"automatic\"\n```\n\nCreate an encryption key (you can use your own, this example generates a random one):\n\n```\nopenssl rand -base64 -out my-encryption-key 42\n```\n\nCreate a secret for this encryption key (replace \"my-encryption-key\" if you are supplying your own):\n\n```\ngcloud secrets create n8n-encryption-key \\\n --data-file=my-encryption-key \\\n --replication-policy=\"automatic\"\n```\n\nNow you can delete my-encryption-key and the database password files you created. These values are now securely stored in Secret Manager.\n\n## Create a service account for Cloud Run\n\nYou want this Cloud Run service to be restricted to access only the resources it needs. The following commands create the service account and adds the permissions necessary to access secrets and the database:\n\n```\ngcloud iam service-accounts create n8n-service-account \\\n --display-name=\"n8n Service Account\"\n\ngcloud secrets add-iam-policy-binding n8n-db-password \\\n --member=\"serviceAccount:n8n-service-account@$PROJECT_ID.iam.gserviceaccount.com\" \\\n --role=\"roles/secretmanager.secretAccessor\"\n\ngcloud secrets add-iam-policy-binding n8n-encryption-key \\\n --member=\"serviceAccount:n8n-service-account@$PROJECT_ID.iam.gserviceaccount.com\" \\\n --role=\"roles/secretmanager.secretAccessor\"\n\ngcloud projects add-iam-policy-binding $PROJECT_ID \\\n --member=\"serviceAccount:n8n-service-account@$PROJECT_ID.iam.gserviceaccount.com\" \\\n --role=\"roles/cloudsql.client\"\n```\n\n## Deploy the Cloud Run service\n\nNow you can deploy your n8n service:\n\n```\ngcloud run deploy n8n \\\n --image=n8nio/n8n:latest \\\n --command=\"/bin/sh\" \\\n --args=\"-c,sleep 5;n8n start\" \\\n --region=$REGION \\\n --allow-unauthenticated \\\n --port=5678 \\\n --memory=2Gi \\\n --no-cpu-throttling \\\n --set-env-vars=\"N8N_PORT=5678,N8N_PROTOCOL=https,N8N_ENDPOINT_HEALTH=health,DB_TYPE=postgresdb,DB_POSTGRESDB_DATABASE=n8n,DB_POSTGRESDB_USER=n8n-user,DB_POSTGRESDB_HOST=/cloudsql/$PROJECT_ID:$REGION:n8n-db,DB_POSTGRESDB_PORT=5432,DB_POSTGRESDB_SCHEMA=public,GENERIC_TIMEZONE=UTC,QUEUE_HEALTH_CHECK_ACTIVE=true\" \\\n --set-secrets=\"DB_POSTGRESDB_PASSWORD=n8n-db-password:latest,N8N_ENCRYPTION_KEY=n8n-encryption-key:latest\" \\\n --add-cloudsql-instances=$PROJECT_ID:$REGION:n8n-db \\\n --service-account=n8n-service-account@$PROJECT_ID.iam.gserviceaccount.com\n```\n\nOnce the deployment finishes, open another tab to navigate to the Service URL. You should see the n8n login screen.\n\n## Troubleshooting\n\nIf you see a \"Cannot GET /\" screen this usually indicates that n8n is still starting up. You can refresh the page and it should eventually load.\n\n## (Optional) Enabling Google Workspace services as n8n tools\n\nIf you want to use Google Workspace services (Gmail, Calendar, Drive, etc.) as tools in n8n, it's recommended to setup OAuth to access these services.\n\nFirst ensure the respective APIs you want are enabled:\n\n```\n## Enable whichever APIs you need\n## Note: If you want Sheets/Docs, it's not enough to just enable Drive; these services each have their own API\ngcloud services enable gmail.googleapis.com\ngcloud services enable drive.googleapis.com\ngcloud services enable sheets.googleapis.com\ngcloud services enable docs.googleapis.com\ngcloud services enable calendar-json.googleapis.com\n```\n\nRe-deploy n8n on Cloud Run with the necessary OAuth callback URLs as environment variables:\n\n```\nexport SERVICE_URL=\"your-n8n-service-URL\"\n## e.g. https://n8n-12345678.us-west1.run.app\n\ngcloud run services update n8n \\\n --region=$REGION \\\n --update-env-vars=\"N8N_HOST=$(echo $SERVICE_URL | sed 's/https:\\/\\///'),WEBHOOK_URL=$SERVICE_URL,N8N_EDITOR_BASE_URL=$SERVICE_URL\"\n```\n\nLastly, you must setup OAuth for these services. Visit `https://console.cloud.google.com/auth` and follow these steps:\n\n1. Click \"Get Started\" if this button shows (when you have not yet setup OAuth in this Cloud project).\n1. For \"App Information\", enter whichever \"App Name\" and \"User Support Email\" you prefer.\n1. For \"Audience\", select \"Internal\" if you intend to only enable access to your user(s) within this same Google Workspace. Otherwise, you can select \"External\".\n1. Enter \"Contact Information\".\n1. If you selected \"External\", then click \"Audience\" and add any test users you need to grant access.\n1. Click \"Clients\" > \"Create client\", select \"Web application\" for \"Application type\", enter your n8n service URL into \"Authorized JavaScript origins\", and \"/rest/oauth2-credential/callback\" into \"Authorized redirect URIs\" where your YOUR-N8N-URL is also the n8n service URL (e.g. `https://n8n-12345678.us-west1.run.app/rest/oauth2-credential/callback`). Make sure you download the created client's JSON file since it contains the client secret which you will not be able to see later in the Console.\n1. Click \"Data Access\" and add the scopes you want n8n to have access for (e.g. to access Google Sheets, you need `https://googleapis.com/auth/drive.file` and `https://googleapis.com/auth/spreadsheets`)\n1. Now you should be able to use these workspace services. You can test if it works by logging into n8n, add a Tool for the respective service and add its credentials using the information in the OAuth client JSON file from step 6.\n",
17583
+ "markdown": "# Hosting n8n on Google Cloud Run\n\nThis hosting guide shows you how to self-host n8n on Google Cloud Run, a serverless container runtime. If you're just getting started with n8n and don't need a production-grade deployment, you can go with the \"easy mode\" option below for deployment. Otherwise, if you intend to use this n8n deployment at-scale, refer to the \"durable mode\" instructions further down.\n\nYou can also enable access via OAuth to Google Workspace, such as Gmail and Drive, to use these services as n8n workflow tools. Instructions for granting n8n access to these services are at the end of this documentation.\n\nIf you want to deploy to Google Kubernetes Engine (GKE) instead, you can refer to [these instructions](../google-kubernetes-engine/).\n\nSelf-hosting knowledge prerequisites\n\nSelf-hosting n8n requires technical knowledge, including:\n\n- Setting up and configuring servers and containers\n- Managing application resources and scaling\n- Securing servers and applications\n- Configuring n8n\n\nn8n recommends self-hosting for expert users. Mistakes can lead to data loss, security issues, and downtime. If you aren't experienced at managing servers, n8n recommends [n8n Cloud](https://n8n.io/cloud/).\n\nStable and Beta versions\n\nn8n releases a new minor version most weeks. The `stable` version is for production use. `beta` is the most recent release. The `beta` version may be unstable. To report issues, use the [forum](https://community.n8n.io/c/questions/12).\n\nCurrent `stable`: 2.19.5 Current `beta`: 2.20.5\n\n## Before you begin: get a Google Cloud project\n\nIf you have not yet created a Google Cloud project, [do this first](https://developers.google.com/workspace/guides/create-project) (and ensure you have billing enabled on the project; even if your Cloud Run service runs for free you must have billing activated to deploy). Otherwise, navigate to the project where you want to deploy n8n.\n\n## Easy mode\n\nThis is the fastest way to deploy n8n on Cloud Run. For this deployment, n8n's data is in-memory so this is only recommended for demo purposes. **Anytime this Cloud Run service scales to zero or is redeployed, the n8n data will be lost.** Refer to the durable mode instructions below if you need a production-grade deployment.\n\nIf you have not yet created a Google Cloud project, [do this first](https://developers.google.com/workspace/guides/create-project) (and ensure you have billing enabled on the project; even if your Cloud Run service will run for free you must have billing enabled to activated to deploy). Otherwise, navigate to the project where you want to deploy n8n.\n\nOpen the Cloud Shell Terminal (on the Google Cloud console, either type \"G\" then \"S\" or click on the terminal icon on the upper right).\n\nOnce your session is open, you may need to run this command first to login (and follow the steps it asks you to complete):\n\n```\ngcloud auth login\n```\n\nYou can also explicitly enable the Cloud Run API (even if you don't do this, it will ask if you want this enabled when you deploy):\n\n```\ngcloud services enable run.googleapis.com\n```\n\nRequired: Custom health check endpoint\n\nGoogle Cloud Run reserves `/healthz` for its own health checks. Since n8n uses this path by default, it can conflict and cause connection issues in the workflow canvas. To fix this, set the `N8N_ENDPOINT_HEALTH` environment variable to a custom path (included in the deployment commands below).\n\nTo deploy n8n:\n\n```\ngcloud run deploy n8n \\\n --image=n8nio/n8n \\\n --region=us-west1 \\\n --allow-unauthenticated \\\n --port=5678 \\\n --no-cpu-throttling \\\n --memory=2Gi \\\n --set-env-vars=\"N8N_ENDPOINT_HEALTH=health\"\n```\n\n(you can specify whichever region you prefer, instead of \"us-west1\")\n\nOnce the deployment finishes, open another tab to navigate to the Service URL. n8n may still be loading and you will see a \"n8n is starting up. Please wait\" message, but shortly thereafter you should see the n8n login screen.\n\nOptional: If you want to keep this n8n service running for as long as possible to avoid data loss, you can also set manual scale to 1 to prevent it from autoscaling to 0.\n\n```\ngcloud run deploy n8n \\\n --image=n8nio/n8n \\\n --region=us-west1 \\\n --allow-unauthenticated \\\n --port=5678 \\\n --no-cpu-throttling \\\n --memory=2Gi \\\n --scaling=1 \\\n --set-env-vars=\"N8N_ENDPOINT_HEALTH=health\"\n```\n\nThis does not prevent data loss completely, such as whenever the Cloud Run service is re-deployed/updated. If you want truly persistent data, you should refer to the instructions below for how to attach a database.\n\n## Durable mode\n\nThe following instructions are intended for a more durable, production-grade deployment of n8n on Cloud Run. It includes resources such as a database for persistance and secret manager for sensitive data.\n\nIf you want to deploy the following setup via Terraform, refer to this [example](https://github.com/ryanpei/n8n-hosting/tree/main/google-cloud-run) which deploys the same setup as the following (without the OAuth setup for Google Workspace tools).\n\n## Enable APIs and set env vars\n\nOpen the Cloud Shell Terminal (on the Google Cloud console, either type \"G\" then \"S\" or click on the terminal icon on the upper right) and run these commands in the terminal session:\n\n```\n## You may need to login first\ngcloud auth login\n\ngcloud services enable run.googleapis.com\ngcloud services enable sqladmin.googleapis.com\ngcloud services enable secretmanager.googleapis.com\n```\n\nYou'll also want to set some environment variables for the remainder of these instructions:\n\n```\nexport PROJECT_ID=your-project\nexport REGION=region-where-you-want-this-deployed\n```\n\n## Setup your Postgres database\n\nRun this command to create the Postgres DB instance (it will take a few minutes to complete; also ensure you update the root-password field with your own desired password):\n\n```\ngcloud sql instances create n8n-db \\\n --database-version=POSTGRES_13 \\\n --tier=db-f1-micro \\\n --region=$REGION \\\n --root-password=\"change-this-password\" \\\n --storage-size=10GB \\\n --availability-type=ZONAL \\\n --no-backup \\\n --storage-type=HDD\n```\n\nOnce complete, you can add the database that n8n will use:\n\n```\ngcloud sql databases create n8n --instance=n8n-db\n```\n\nCreate the DB user for n8n (change the password value, of course):\n\n```\ngcloud sql users create n8n-user \\\n --instance=n8n-db \\\n --password=\"change-this-password\"\n```\n\nYou can save the password you set for this n8n-user to a file for the next step of saving the password in Secret Manager. Be sure to delete this file later.\n\n## Store sensitive data in Secret Manager\n\nWhile not required, it's absolutely recommended to store your sensitive data in Secrets Manager.\n\nCreate a secret for the database password (replace \"/your/password/file\" with the file you created above for the n8n-user password):\n\n```\ngcloud secrets create n8n-db-password \\\n --data-file=/your/password/file \\\n --replication-policy=\"automatic\"\n```\n\nCreate an encryption key (you can use your own, this example generates a random one):\n\n```\nopenssl rand -base64 -out my-encryption-key 42\n```\n\nCreate a secret for this encryption key (replace \"my-encryption-key\" if you are supplying your own):\n\n```\ngcloud secrets create n8n-encryption-key \\\n --data-file=my-encryption-key \\\n --replication-policy=\"automatic\"\n```\n\nNow you can delete my-encryption-key and the database password files you created. These values are now securely stored in Secret Manager.\n\n## Create a service account for Cloud Run\n\nYou want this Cloud Run service to be restricted to access only the resources it needs. The following commands create the service account and adds the permissions necessary to access secrets and the database:\n\n```\ngcloud iam service-accounts create n8n-service-account \\\n --display-name=\"n8n Service Account\"\n\ngcloud secrets add-iam-policy-binding n8n-db-password \\\n --member=\"serviceAccount:n8n-service-account@$PROJECT_ID.iam.gserviceaccount.com\" \\\n --role=\"roles/secretmanager.secretAccessor\"\n\ngcloud secrets add-iam-policy-binding n8n-encryption-key \\\n --member=\"serviceAccount:n8n-service-account@$PROJECT_ID.iam.gserviceaccount.com\" \\\n --role=\"roles/secretmanager.secretAccessor\"\n\ngcloud projects add-iam-policy-binding $PROJECT_ID \\\n --member=\"serviceAccount:n8n-service-account@$PROJECT_ID.iam.gserviceaccount.com\" \\\n --role=\"roles/cloudsql.client\"\n```\n\n## Deploy the Cloud Run service\n\nNow you can deploy your n8n service:\n\n```\ngcloud run deploy n8n \\\n --image=n8nio/n8n:latest \\\n --command=\"/bin/sh\" \\\n --args=\"-c,sleep 5;n8n start\" \\\n --region=$REGION \\\n --allow-unauthenticated \\\n --port=5678 \\\n --memory=2Gi \\\n --no-cpu-throttling \\\n --set-env-vars=\"N8N_PORT=5678,N8N_PROTOCOL=https,N8N_ENDPOINT_HEALTH=health,DB_TYPE=postgresdb,DB_POSTGRESDB_DATABASE=n8n,DB_POSTGRESDB_USER=n8n-user,DB_POSTGRESDB_HOST=/cloudsql/$PROJECT_ID:$REGION:n8n-db,DB_POSTGRESDB_PORT=5432,DB_POSTGRESDB_SCHEMA=public,GENERIC_TIMEZONE=UTC,QUEUE_HEALTH_CHECK_ACTIVE=true\" \\\n --set-secrets=\"DB_POSTGRESDB_PASSWORD=n8n-db-password:latest,N8N_ENCRYPTION_KEY=n8n-encryption-key:latest\" \\\n --add-cloudsql-instances=$PROJECT_ID:$REGION:n8n-db \\\n --service-account=n8n-service-account@$PROJECT_ID.iam.gserviceaccount.com\n```\n\nOnce the deployment finishes, open another tab to navigate to the Service URL. You should see the n8n login screen.\n\n## Troubleshooting\n\nIf you see a \"Cannot GET /\" screen this usually indicates that n8n is still starting up. You can refresh the page and it should eventually load.\n\n## (Optional) Enabling Google Workspace services as n8n tools\n\nIf you want to use Google Workspace services (Gmail, Calendar, Drive, etc.) as tools in n8n, it's recommended to setup OAuth to access these services.\n\nFirst ensure the respective APIs you want are enabled:\n\n```\n## Enable whichever APIs you need\n## Note: If you want Sheets/Docs, it's not enough to just enable Drive; these services each have their own API\ngcloud services enable gmail.googleapis.com\ngcloud services enable drive.googleapis.com\ngcloud services enable sheets.googleapis.com\ngcloud services enable docs.googleapis.com\ngcloud services enable calendar-json.googleapis.com\n```\n\nRe-deploy n8n on Cloud Run with the necessary OAuth callback URLs as environment variables:\n\n```\nexport SERVICE_URL=\"your-n8n-service-URL\"\n## e.g. https://n8n-12345678.us-west1.run.app\n\ngcloud run services update n8n \\\n --region=$REGION \\\n --update-env-vars=\"N8N_HOST=$(echo $SERVICE_URL | sed 's/https:\\/\\///'),WEBHOOK_URL=$SERVICE_URL,N8N_EDITOR_BASE_URL=$SERVICE_URL\"\n```\n\nLastly, you must setup OAuth for these services. Visit `https://console.cloud.google.com/auth` and follow these steps:\n\n1. Click \"Get Started\" if this button shows (when you have not yet setup OAuth in this Cloud project).\n1. For \"App Information\", enter whichever \"App Name\" and \"User Support Email\" you prefer.\n1. For \"Audience\", select \"Internal\" if you intend to only enable access to your user(s) within this same Google Workspace. Otherwise, you can select \"External\".\n1. Enter \"Contact Information\".\n1. If you selected \"External\", then click \"Audience\" and add any test users you need to grant access.\n1. Click \"Clients\" > \"Create client\", select \"Web application\" for \"Application type\", enter your n8n service URL into \"Authorized JavaScript origins\", and \"/rest/oauth2-credential/callback\" into \"Authorized redirect URIs\" where your YOUR-N8N-URL is also the n8n service URL (e.g. `https://n8n-12345678.us-west1.run.app/rest/oauth2-credential/callback`). Make sure you download the created client's JSON file since it contains the client secret which you will not be able to see later in the Console.\n1. Click \"Data Access\" and add the scopes you want n8n to have access for (e.g. to access Google Sheets, you need `https://googleapis.com/auth/drive.file` and `https://googleapis.com/auth/spreadsheets`)\n1. Now you should be able to use these workspace services. You can test if it works by logging into n8n, add a Tool for the respective service and add its credentials using the information in the OAuth client JSON file from step 6.\n",
17584
17584
  "excerpt": "# Hosting n8n on Google Cloud Run This hosting guide shows you how to self-host n8n on Google Cloud Run, a serverless container runtime. If you're just getting started with n8n and don't need a production-grade deployment, you can go with the \"easy mode\" option below for deployment. Otherwise, if you intend to use this n8n deployment at-scale, refer to the \"durable mode\" instructions further down. You can also enable access via OAuth to Google Workspace, such as Gmail and Drive, to use these s...",
17585
17585
  "sections": [
17586
17586
  {
17587
17587
  "title": "Hosting n8n on Google Cloud Run",
17588
17588
  "level": 1,
17589
- "content": "This hosting guide shows you how to self-host n8n on Google Cloud Run, a serverless container runtime. If you're just getting started with n8n and don't need a production-grade deployment, you can go with the \"easy mode\" option below for deployment. Otherwise, if you intend to use this n8n deployment at-scale, refer to the \"durable mode\" instructions further down.\n\nYou can also enable access via OAuth to Google Workspace, such as Gmail and Drive, to use these services as n8n workflow tools. Instructions for granting n8n access to these services are at the end of of this documentation.\n\nIf you want to deploy to Google Kubernetes Engine (GKE) instead, you can refer to [these instructions](../google-kubernetes-engine/).\n\nSelf-hosting knowledge prerequisites\n\nSelf-hosting n8n requires technical knowledge, including:\n\n- Setting up and configuring servers and containers\n- Managing application resources and scaling\n- Securing servers and applications\n- Configuring n8n\n\nn8n recommends self-hos"
17589
+ "content": "This hosting guide shows you how to self-host n8n on Google Cloud Run, a serverless container runtime. If you're just getting started with n8n and don't need a production-grade deployment, you can go with the \"easy mode\" option below for deployment. Otherwise, if you intend to use this n8n deployment at-scale, refer to the \"durable mode\" instructions further down.\n\nYou can also enable access via OAuth to Google Workspace, such as Gmail and Drive, to use these services as n8n workflow tools. Instructions for granting n8n access to these services are at the end of this documentation.\n\nIf you want to deploy to Google Kubernetes Engine (GKE) instead, you can refer to [these instructions](../google-kubernetes-engine/).\n\nSelf-hosting knowledge prerequisites\n\nSelf-hosting n8n requires technical knowledge, including:\n\n- Setting up and configuring servers and containers\n- Managing application resources and scaling\n- Securing servers and applications\n- Configuring n8n\n\nn8n recommends self-hostin"
17590
17590
  }
17591
17591
  ]
17592
17592
  },
@@ -17647,11 +17647,11 @@
17647
17647
  "codeExamples": 16,
17648
17648
  "complexity": "intermediate",
17649
17649
  "readingTime": "9 min",
17650
- "contentLength": 12168,
17650
+ "contentLength": 12165,
17651
17651
  "relatedPages": []
17652
17652
  },
17653
17653
  "searchIndex": {
17654
- "fullText": "google cloud run # hosting n8n on google cloud run\n\nthis hosting guide shows you how to self-host n8n on google cloud run, a serverless container runtime. if you're just getting started with n8n and don't need a production-grade deployment, you can go with the \"easy mode\" option below for deployment. otherwise, if you intend to use this n8n deployment at-scale, refer to the \"durable mode\" instructions further down.\n\nyou can also enable access via oauth to google workspace, such as gmail and drive, to use these services as n8n workflow tools. instructions for granting n8n access to these services are at the end of of this documentation.\n\nif you want to deploy to google kubernetes engine (gke) instead, you can refer to [these instructions](../google-kubernetes-engine/).\n\nself-hosting knowledge prerequisites\n\nself-hosting n8n requires technical knowledge, including:\n\n- setting up and configuring servers and containers\n- managing application resources and scaling\n- securing servers and applications\n- configuring n8n\n\nn8n recommends self-hosting for expert users. mistakes can lead to data loss, security issues, and downtime. if you aren't experienced at managing servers, n8n recommends [n8n cloud](https://n8n.io/cloud/).\n\nstable and beta versions\n\nn8n releases a new minor version most weeks. the `stable` version is for production use. `beta` is the most recent release. the `beta` version may be unstable. to report issues, use the [forum](https://community.n8n.io/c/questions/12).\n\ncurrent `stable`: 2.19.5 current `beta`: 2.20.5\n\n## before you begin: get a google cloud project\n\nif you have not yet created a google cloud project, [do this first](https://developers.google.com/workspace/guides/create-project) (and ensure you have billing enabled on the project; even if your cloud run service runs for free you must have billing activated to deploy). otherwise, navigate to the project where you want to deploy n8n.\n\n## easy mode\n\nthis is the fastest way to deploy n8n on cloud run. for this deployment, n8n's data is in-memory so this is only recommended for demo purposes. **anytime this cloud run service scales to zero or is redeployed, the n8n data will be lost.** refer to the durable mode instructions below if you need a production-grade deployment.\n\nif you have not yet created a google cloud project, [do this first](https://developers.google.com/workspace/guides/create-project) (and ensure you have billing enabled on the project; even if your cloud run service will run for free you must have billing enabled to activated to deploy). otherwise, navigate to the project where you want to deploy n8n.\n\nopen the cloud shell terminal (on the google cloud console, either type \"g\" then \"s\" or click on the terminal icon on the upper right).\n\nonce your session is open, you may need to run this command first to login (and follow the steps it asks you to complete):\n\n```\ngcloud auth login\n```\n\nyou can also explicitly enable the cloud run api (even if you don't do this, it will ask if you want this enabled when you deploy):\n\n```\ngcloud services enable run.googleapis.com\n```\n\nrequired: custom health check endpoint\n\ngoogle cloud run reserves `/healthz` for its own health checks. since n8n uses this path by default, it can conflict and cause connection issues in the workflow canvas. to fix this, set the `n8n_endpoint_health` environment variable to a custom path (included in the deployment commands below).\n\nto deploy n8n:\n\n```\ngcloud run deploy n8n \\\n --image=n8nio/n8n \\\n --region=us-west1 \\\n --allow-unauthenticated \\\n --port=5678 \\\n --no-cpu-throttling \\\n --memory=2gi \\\n --set-env-vars=\"n8n_endpoint_health=health\"\n```\n\n(you can specify whichever region you prefer, instead of \"us-west1\")\n\nonce the deployment finishes, open another tab to navigate to the service url. n8n may still be loading and you will see a \"n8n is starting up. please wait\" message, but shortly thereafter you should see the n8n login screen.\n\noptional: if you want to keep this n8n service running for as long as possible to avoid data loss, you can also set manual scale to 1 to prevent it from autoscaling to 0.\n\n```\ngcloud run deploy n8n \\\n --image=n8nio/n8n \\\n --region=us-west1 \\\n --allow-unauthenticated \\\n --port=5678 \\\n --no-cpu-throttling \\\n --memory=2gi \\\n --scaling=1 \\\n --set-env-vars=\"n8n_endpoint_health=health\"\n```\n\nthis does not prevent data loss completely, such as whenever the cloud run service is re-deployed/updated. if you want truly persistant data, you should refer to the instructions below for how to attach a database.\n\n## durable mode\n\nthe following instructions are intended for a more durable, production-grade deployment of n8n on cloud run. it includes resources such as a database for persistance and secret manager for sensitive data.\n\nif you want to deploy the following setup via terraform, refer to this [example](https://github.com/ryanpei/n8n-hosting/tree/main/google-cloud-run) which deploys the same setup as the following (without the oauth setup for google workspace tools).\n\n## enable apis and set env vars\n\nopen the cloud shell terminal (on the google cloud console, either type \"g\" then \"s\" or click on the terminal icon on the upper right) and run these commands in the terminal session:\n\n```\n## you may need to login first\ngcloud auth login\n\ngcloud services enable run.googleapis.com\ngcloud services enable sqladmin.googleapis.com\ngcloud services enable secretmanager.googleapis.com\n```\n\nyou'll also want to set some environment variables for the remainder of these instructions:\n\n```\nexport project_id=your-project\nexport region=region-where-you-want-this-deployed\n```\n\n## setup your postgres database\n\nrun this command to create the postgres db instance (it will take a few minutes to complete; also ensure you update the root-password field with your own desired password):\n\n```\ngcloud sql instances create n8n-db \\\n --database-version=postgres_13 \\\n --tier=db-f1-micro \\\n --region=$region \\\n --root-password=\"change-this-password\" \\\n --storage-size=10gb \\\n --availability-type=zonal \\\n --no-backup \\\n --storage-type=hdd\n```\n\nonce complete, you can add the database that n8n will use:\n\n```\ngcloud sql databases create n8n --instance=n8n-db\n```\n\ncreate the db user for n8n (change the password value, of course):\n\n```\ngcloud sql users create n8n-user \\\n --instance=n8n-db \\\n --password=\"change-this-password\"\n```\n\nyou can save the password you set for this n8n-user to a file for the next step of saving the password in secret manager. be sure to delete this file later.\n\n## store sensitive data in secret manager\n\nwhile not required, it's absolutely recommended to store your sensitive data in secrets manager.\n\ncreate a secret for the database password (replace \"/your/password/file\" with the file you created above for the n8n-user password):\n\n```\ngcloud secrets create n8n-db-password \\\n --data-file=/your/password/file \\\n --replication-policy=\"automatic\"\n```\n\ncreate an encryption key (you can use your own, this example generates a random one):\n\n```\nopenssl rand -base64 -out my-encryption-key 42\n```\n\ncreate a secret for this encryption key (replace \"my-encryption-key\" if you are supplying your own):\n\n```\ngcloud secrets create n8n-encryption-key \\\n --data-file=my-encryption-key \\\n --replication-policy=\"automatic\"\n```\n\nnow you can delete my-encryption-key and the database password files you created. these values are now securely stored in secret manager.\n\n## create a service account for cloud run\n\nyou want this cloud run service to be restricted to access only the resources it needs. the following commands create the service account and adds the permissions necessary to access secrets and the database:\n\n```\ngcloud iam service-accounts create n8n-service-account \\\n --display-name=\"n8n service account\"\n\ngcloud secrets add-iam-policy-binding n8n-db-password \\\n --member=\"serviceaccount:n8n-service-account@$project_id.iam.gserviceaccount.com\" \\\n --role=\"roles/secretmanager.secretaccessor\"\n\ngcloud secrets add-iam-policy-binding n8n-encryption-key \\\n --member=\"serviceaccount:n8n-service-account@$project_id.iam.gserviceaccount.com\" \\\n --role=\"roles/secretmanager.secretaccessor\"\n\ngcloud projects add-iam-policy-binding $project_id \\\n --member=\"serviceaccount:n8n-service-account@$project_id.iam.gserviceaccount.com\" \\\n --role=\"roles/cloudsql.client\"\n```\n\n## deploy the cloud run service\n\nnow you can deploy your n8n service:\n\n```\ngcloud run deploy n8n \\\n --image=n8nio/n8n:latest \\\n --command=\"/bin/sh\" \\\n --args=\"-c,sleep 5;n8n start\" \\\n --region=$region \\\n --allow-unauthenticated \\\n --port=5678 \\\n --memory=2gi \\\n --no-cpu-throttling \\\n --set-env-vars=\"n8n_port=5678,n8n_protocol=https,n8n_endpoint_health=health,db_type=postgresdb,db_postgresdb_database=n8n,db_postgresdb_user=n8n-user,db_postgresdb_host=/cloudsql/$project_id:$region:n8n-db,db_postgresdb_port=5432,db_postgresdb_schema=public,generic_timezone=utc,queue_health_check_active=true\" \\\n --set-secrets=\"db_postgresdb_password=n8n-db-password:latest,n8n_encryption_key=n8n-encryption-key:latest\" \\\n --add-cloudsql-instances=$project_id:$region:n8n-db \\\n --service-account=n8n-service-account@$project_id.iam.gserviceaccount.com\n```\n\nonce the deployment finishes, open another tab to navigate to the service url. you should see the n8n login screen.\n\n## troubleshooting\n\nif you see a \"cannot get /\" screen this usually indicates that n8n is still starting up. you can refresh the page and it should eventually load.\n\n## (optional) enabling google workspace services as n8n tools\n\nif you want to use google workspace services (gmail, calendar, drive, etc.) as tools in n8n, it's recommended to setup oauth to access these services.\n\nfirst ensure the respective apis you want are enabled:\n\n```\n## enable whichever apis you need\n## note: if you want sheets/docs, it's not enough to just enable drive; these services",
17654
+ "fullText": "google cloud run # hosting n8n on google cloud run\n\nthis hosting guide shows you how to self-host n8n on google cloud run, a serverless container runtime. if you're just getting started with n8n and don't need a production-grade deployment, you can go with the \"easy mode\" option below for deployment. otherwise, if you intend to use this n8n deployment at-scale, refer to the \"durable mode\" instructions further down.\n\nyou can also enable access via oauth to google workspace, such as gmail and drive, to use these services as n8n workflow tools. instructions for granting n8n access to these services are at the end of this documentation.\n\nif you want to deploy to google kubernetes engine (gke) instead, you can refer to [these instructions](../google-kubernetes-engine/).\n\nself-hosting knowledge prerequisites\n\nself-hosting n8n requires technical knowledge, including:\n\n- setting up and configuring servers and containers\n- managing application resources and scaling\n- securing servers and applications\n- configuring n8n\n\nn8n recommends self-hosting for expert users. mistakes can lead to data loss, security issues, and downtime. if you aren't experienced at managing servers, n8n recommends [n8n cloud](https://n8n.io/cloud/).\n\nstable and beta versions\n\nn8n releases a new minor version most weeks. the `stable` version is for production use. `beta` is the most recent release. the `beta` version may be unstable. to report issues, use the [forum](https://community.n8n.io/c/questions/12).\n\ncurrent `stable`: 2.19.5 current `beta`: 2.20.5\n\n## before you begin: get a google cloud project\n\nif you have not yet created a google cloud project, [do this first](https://developers.google.com/workspace/guides/create-project) (and ensure you have billing enabled on the project; even if your cloud run service runs for free you must have billing activated to deploy). otherwise, navigate to the project where you want to deploy n8n.\n\n## easy mode\n\nthis is the fastest way to deploy n8n on cloud run. for this deployment, n8n's data is in-memory so this is only recommended for demo purposes. **anytime this cloud run service scales to zero or is redeployed, the n8n data will be lost.** refer to the durable mode instructions below if you need a production-grade deployment.\n\nif you have not yet created a google cloud project, [do this first](https://developers.google.com/workspace/guides/create-project) (and ensure you have billing enabled on the project; even if your cloud run service will run for free you must have billing enabled to activated to deploy). otherwise, navigate to the project where you want to deploy n8n.\n\nopen the cloud shell terminal (on the google cloud console, either type \"g\" then \"s\" or click on the terminal icon on the upper right).\n\nonce your session is open, you may need to run this command first to login (and follow the steps it asks you to complete):\n\n```\ngcloud auth login\n```\n\nyou can also explicitly enable the cloud run api (even if you don't do this, it will ask if you want this enabled when you deploy):\n\n```\ngcloud services enable run.googleapis.com\n```\n\nrequired: custom health check endpoint\n\ngoogle cloud run reserves `/healthz` for its own health checks. since n8n uses this path by default, it can conflict and cause connection issues in the workflow canvas. to fix this, set the `n8n_endpoint_health` environment variable to a custom path (included in the deployment commands below).\n\nto deploy n8n:\n\n```\ngcloud run deploy n8n \\\n --image=n8nio/n8n \\\n --region=us-west1 \\\n --allow-unauthenticated \\\n --port=5678 \\\n --no-cpu-throttling \\\n --memory=2gi \\\n --set-env-vars=\"n8n_endpoint_health=health\"\n```\n\n(you can specify whichever region you prefer, instead of \"us-west1\")\n\nonce the deployment finishes, open another tab to navigate to the service url. n8n may still be loading and you will see a \"n8n is starting up. please wait\" message, but shortly thereafter you should see the n8n login screen.\n\noptional: if you want to keep this n8n service running for as long as possible to avoid data loss, you can also set manual scale to 1 to prevent it from autoscaling to 0.\n\n```\ngcloud run deploy n8n \\\n --image=n8nio/n8n \\\n --region=us-west1 \\\n --allow-unauthenticated \\\n --port=5678 \\\n --no-cpu-throttling \\\n --memory=2gi \\\n --scaling=1 \\\n --set-env-vars=\"n8n_endpoint_health=health\"\n```\n\nthis does not prevent data loss completely, such as whenever the cloud run service is re-deployed/updated. if you want truly persistent data, you should refer to the instructions below for how to attach a database.\n\n## durable mode\n\nthe following instructions are intended for a more durable, production-grade deployment of n8n on cloud run. it includes resources such as a database for persistance and secret manager for sensitive data.\n\nif you want to deploy the following setup via terraform, refer to this [example](https://github.com/ryanpei/n8n-hosting/tree/main/google-cloud-run) which deploys the same setup as the following (without the oauth setup for google workspace tools).\n\n## enable apis and set env vars\n\nopen the cloud shell terminal (on the google cloud console, either type \"g\" then \"s\" or click on the terminal icon on the upper right) and run these commands in the terminal session:\n\n```\n## you may need to login first\ngcloud auth login\n\ngcloud services enable run.googleapis.com\ngcloud services enable sqladmin.googleapis.com\ngcloud services enable secretmanager.googleapis.com\n```\n\nyou'll also want to set some environment variables for the remainder of these instructions:\n\n```\nexport project_id=your-project\nexport region=region-where-you-want-this-deployed\n```\n\n## setup your postgres database\n\nrun this command to create the postgres db instance (it will take a few minutes to complete; also ensure you update the root-password field with your own desired password):\n\n```\ngcloud sql instances create n8n-db \\\n --database-version=postgres_13 \\\n --tier=db-f1-micro \\\n --region=$region \\\n --root-password=\"change-this-password\" \\\n --storage-size=10gb \\\n --availability-type=zonal \\\n --no-backup \\\n --storage-type=hdd\n```\n\nonce complete, you can add the database that n8n will use:\n\n```\ngcloud sql databases create n8n --instance=n8n-db\n```\n\ncreate the db user for n8n (change the password value, of course):\n\n```\ngcloud sql users create n8n-user \\\n --instance=n8n-db \\\n --password=\"change-this-password\"\n```\n\nyou can save the password you set for this n8n-user to a file for the next step of saving the password in secret manager. be sure to delete this file later.\n\n## store sensitive data in secret manager\n\nwhile not required, it's absolutely recommended to store your sensitive data in secrets manager.\n\ncreate a secret for the database password (replace \"/your/password/file\" with the file you created above for the n8n-user password):\n\n```\ngcloud secrets create n8n-db-password \\\n --data-file=/your/password/file \\\n --replication-policy=\"automatic\"\n```\n\ncreate an encryption key (you can use your own, this example generates a random one):\n\n```\nopenssl rand -base64 -out my-encryption-key 42\n```\n\ncreate a secret for this encryption key (replace \"my-encryption-key\" if you are supplying your own):\n\n```\ngcloud secrets create n8n-encryption-key \\\n --data-file=my-encryption-key \\\n --replication-policy=\"automatic\"\n```\n\nnow you can delete my-encryption-key and the database password files you created. these values are now securely stored in secret manager.\n\n## create a service account for cloud run\n\nyou want this cloud run service to be restricted to access only the resources it needs. the following commands create the service account and adds the permissions necessary to access secrets and the database:\n\n```\ngcloud iam service-accounts create n8n-service-account \\\n --display-name=\"n8n service account\"\n\ngcloud secrets add-iam-policy-binding n8n-db-password \\\n --member=\"serviceaccount:n8n-service-account@$project_id.iam.gserviceaccount.com\" \\\n --role=\"roles/secretmanager.secretaccessor\"\n\ngcloud secrets add-iam-policy-binding n8n-encryption-key \\\n --member=\"serviceaccount:n8n-service-account@$project_id.iam.gserviceaccount.com\" \\\n --role=\"roles/secretmanager.secretaccessor\"\n\ngcloud projects add-iam-policy-binding $project_id \\\n --member=\"serviceaccount:n8n-service-account@$project_id.iam.gserviceaccount.com\" \\\n --role=\"roles/cloudsql.client\"\n```\n\n## deploy the cloud run service\n\nnow you can deploy your n8n service:\n\n```\ngcloud run deploy n8n \\\n --image=n8nio/n8n:latest \\\n --command=\"/bin/sh\" \\\n --args=\"-c,sleep 5;n8n start\" \\\n --region=$region \\\n --allow-unauthenticated \\\n --port=5678 \\\n --memory=2gi \\\n --no-cpu-throttling \\\n --set-env-vars=\"n8n_port=5678,n8n_protocol=https,n8n_endpoint_health=health,db_type=postgresdb,db_postgresdb_database=n8n,db_postgresdb_user=n8n-user,db_postgresdb_host=/cloudsql/$project_id:$region:n8n-db,db_postgresdb_port=5432,db_postgresdb_schema=public,generic_timezone=utc,queue_health_check_active=true\" \\\n --set-secrets=\"db_postgresdb_password=n8n-db-password:latest,n8n_encryption_key=n8n-encryption-key:latest\" \\\n --add-cloudsql-instances=$project_id:$region:n8n-db \\\n --service-account=n8n-service-account@$project_id.iam.gserviceaccount.com\n```\n\nonce the deployment finishes, open another tab to navigate to the service url. you should see the n8n login screen.\n\n## troubleshooting\n\nif you see a \"cannot get /\" screen this usually indicates that n8n is still starting up. you can refresh the page and it should eventually load.\n\n## (optional) enabling google workspace services as n8n tools\n\nif you want to use google workspace services (gmail, calendar, drive, etc.) as tools in n8n, it's recommended to setup oauth to access these services.\n\nfirst ensure the respective apis you want are enabled:\n\n```\n## enable whichever apis you need\n## note: if you want sheets/docs, it's not enough to just enable drive; these services ea",
17655
17655
  "importantTerms": [
17656
17656
  "this",
17657
17657
  "cloud",
@@ -18065,7 +18065,7 @@
18065
18065
  "nodeName": null,
18066
18066
  "nodeType": null,
18067
18067
  "content": {
18068
- "markdown": "# Hosting n8n on OpenShift Local (CRC)\n\nThis guide walks you through deploying n8n on OpenShift Local (CRC), Red Hat's tool for running a local OpenShift cluster. It mirrors AWS/EKS deployment, but runs entirely on your local machine. It's designed for testing n8n in an OpenShift environment locally, without cloud costs.\n\nYou will need a machine with significant resources available, given how many resources OpenShift itself consumes.\n\n## OpenShift concepts vs standard Kubernetes\n\nOpenShift is built on Kubernetes but uses different terminology and has stricter security defaults. If you are familiar with standard Kubernetes, or with a guide that targets a managed Kubernetes service such as EKS, the table below maps the equivalent concepts so you know what to expect.\n\n| Standard Kubernetes / EKS | OpenShift Local (CRC) |\n| ---------------------------- | --------------------------------------------------------- |\n| `kubectl` | `oc` (OpenShift CLI; also understands `kubectl` commands) |\n| Namespace | Project (same concept, different command) |\n| Ingress / LoadBalancer | Route (built into OpenShift, no controller needed) |\n| EBS StorageClass (gp3) | CRC built-in storage provisioner (no setup needed) |\n| RDS PostgreSQL | In-cluster PostgreSQL via Helm (Bitnami) |\n| ElastiCache Redis | In-cluster Redis via Helm (Bitnami) |\n| AWS S3 | MinIO in-cluster (S3-compatible) |\n| Pod Identity / IRSA | Access keys via Kubernetes Secret |\n| AWS Load Balancer Controller | Not needed (Routes are built-in) |\n| OIDC / IAM | Not needed |\n| ~$135–400/month | Free (runs on your machine) |\n\n## Prerequisites\n\nBefore starting, confirm your machine has:\n\n- **CPU**: 4 or more physical cores (not just threads) with virtualization support\n- **RAM**: 32+ GB free minimum (CRC reserves 9 GB for its VM)\n- **Disk**: 100 GB free\n- **OS**: Ubuntu (22.04 LTS or newer)\n\n## Prepare Ubuntu\n\n### Open a terminal\n\nPress `Ctrl+Alt+T` or search for **Terminal** in the Applications menu.\n\nEvery command in this guide is typed into the terminal and run by pressing **Enter**.\n\n### Update your system\n\nStart with a system update to avoid dependency issues:\n\n```\nsudo apt update && sudo apt upgrade -y\n```\n\nsudo\n\n`sudo` means “run as administrator”. You will be prompted for your password. Characters you type won't appear on screen, this is normal.\n\n### Check CPU virtualization support\n\nCRC runs a virtual machine. Your CPU must support hardware virtualization:\n\n```\negrep -c '(vmx|svm)' /proc/cpuinfo\n```\n\n- **Output `0`**: Virtualization is disabled. Enter your BIOS/UEFI settings and enable VT-x (Intel) or AMD-V (AMD), then reboot and try again.\n- **Output `1` or higher**: You are good to continue.\n\n### Install KVM and libvirt\n\nKVM is Linux’s built-in hypervisor. CRC uses it to run the OpenShift cluster VM:\n\n```\nsudo apt install -y qemu-kvm libvirt-daemon-system libvirt-clients bridge-utils\n```\n\nInstall `virtiofsd`, which CRC requires to share the filesystem with the cluster VM:\n\n```\nsudo apt install -y virtiofsd\n```\n\nStart the libvirt service and configure it to start automatically on boot:\n\n```\nsudo systemctl start libvirtd\nsudo systemctl enable libvirtd\n```\n\nVerify it's running:\n\n```\nsudo systemctl status libvirtd\n```\n\nLook for `Active: active (running)` in green. Press `q` to exit.\n\n### Add user to required groups\n\nThis allows you to use KVM and libvirt without typing `sudo` for every command:\n\n```\nsudo usermod -aG libvirt $USER\nsudo usermod -aG kvm $USER\n```\n\nWarning\n\n**You must log out and log back in (or reboot) for this to take effect.** If you skip this step, CRC will fail with a “permission denied” error.\n\nReboot now:\n\n```\nsudo reboot\n```\n\nAfter logging back in, open a terminal and verify group membership:\n\n```\ngroups\n```\n\nYou should see `libvirt` and `kvm` listed.\n\n### Install NetworkManager\n\nCRC requires NetworkManager to manage DNS entries for the cluster’s internal domains (`*.apps-crc.testing`, `api.crc.testing`):\n\n```\nsudo apt install -y network-manager\nsudo systemctl start NetworkManager\nsudo systemctl enable NetworkManager\n```\n\nVerify it's connected:\n\n```\nnmcli general status\n```\n\nThe `STATE` column should show `connected`.\n\n## Install tools\n\n### Get a Red Hat account and pull secret\n\nCRC requires a free Red Hat account to pull container images.\n\n1. [Create a free Red Hat account](https://console.redhat.com/), if you don't already have one.\n1. In [console.redhat.com/openshift/create/local](https://console.redhat.com/openshift/create/local), click **Download OpenShift Local**.\n1. Select **Linux**, and download the `.tar.xz` file to `~/Downloads`.\n1. On the same page of the Red Hat console, click **Copy pull secret**. Paste it into a text file and save it for later.\n\n### Install CRC\n\nOpen a terminal in your Downloads folder.\n\n```\ncd ~/Downloads\n```\n\nExtract the archive.\n\n```\ntar xf crc-linux-amd64.tar.xz\n```\n\nMove the `crc` binary to a system-wide location, so it's available in any terminal:\n\n```\nsudo mv crc-*-linux-amd64/crc /usr/local/bin/\n```\n\nVerify the installation:\n\n```\ncrc version\n```\n\nA version number should print to the terminal.\n\n### Install Helm\n\nHelm installs n8n and supporting services into the cluster:\n\n```\ncurl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash\n```\n\nVerify:\n\n```\nhelm version\n```\n\n### Set environment variables\n\n```\nexport NAMESPACE=n8n-$(date +%Y%m%d)\necho \"Namespace:$NAMESPACE\"\n```\n\nVariable persistence\n\nThese variables only last for the current terminal session. Re-run this line whenever you open a new terminal before continuing.\n\n## Start OpenShift Local\n\n### Run CRC setup\n\nYou only need to run this once. It configures KVM networking, checks system requirements, and downloads the CRC bundle (~2.5 GB):\n\n```\ncrc setup\n```\n\nThis takes several minutes. If it reports any missing packages, install them with `sudo apt install -y <package-name>` and re-run.\n\n### Configure CRC memory and start the cluster\n\nCRC defaults to 9 GB of RAM for its VM. n8n and its supporting services need more headroom. Set the memory to 14 GB before starting:\n\n```\ncrc config set memory 14336\n```\n\nYou only need to run this once. The setting persists across `crc stop` / `crc start` cycles.\n\n**Recommended:** Save your pull secret to a file first so you don’t have to paste it every time:\n\n```\n# Open the file, paste your pull secret (from earlier), then Ctrl+O to save, Ctrl+X to exit\nnano ~/pull-secret.txt\n\n# Restrict permissions so only you can read it\nchmod 600 ~/pull-secret.txt\n```\n\nStart CRC using the file:\n\n```\ncrc start --pull-secret-file ~/pull-secret.txt\n```\n\nAlternatively, run `crc start` without the flag and paste the secret when prompted.\n\n**This takes 10–15 minutes.** When complete you will see something like:\n\n```\nStarted the OpenShift cluster.\n\nThe server is accessible via web console at:\n https://console-openshift-console.apps-crc.testing\n\nLog in as administrator:\n Username: kubeadmin\n Password: <generated-password>\n\nLog in as user:\n Username: developer\n Password: developer\n```\n\n**Save the `kubeadmin` password now.** You will need it in the next step. You can retrieve it later using `crc console --credentials`.\n\n### Verify DNS resolution\n\nOn Ubuntu, CRC configures the system resolver automatically with NetworkManager and systemd-resolved. No manual `/etc/hosts` entries are needed.\n\nVerify the API is reachable:\n\n```\nsudo ss -tlnp | grep 6443\n```\n\nYou should see a process bound to `127.0.0.1:6443`. If nothing appears, re-run `crc start`. If DNS doesn't resolve `*.apps-crc.testing`, see the troubleshooting section.\n\n### Configure your shell\n\nCRC bundles the `oc` CLI inside the VM. This command makes it available in your terminal:\n\n```\neval $(crc oc-env)\n```\n\nTo make this permanent so you don't have to run it every time you open a terminal:\n\n```\necho 'eval $(crc oc-env)' >> ~/.bashrc\nsource ~/.bashrc\n```\n\nVerify `oc` works:\n\n```\noc version\n```\n\n### Log in to the cluster\n\n```\noc login -u kubeadmin -p <your-kubeadmin-password> https://api.crc.testing:6443\n```\n\nReplace `<your-kubeadmin-password>` with the password printed when you [configured CRC memory and started the cluster](#configure-crc-memory-and-start-the-cluster).\n\nVerify you are logged in:\n\n```\noc whoami\n```\n\n`kubeadmin` should print to the screen.\n\n## Standalone deployment\n\nStandalone mode runs n8n as a single pod with SQLite. No external database or Redis is required. This is ideal for exploring n8n and testing workflows locally.\n\n### Create the project\n\nIn OpenShift, a **project** is the same as a Kubernetes namespace: an isolated space for your resources:\n\n```\noc new-project $NAMESPACE\n```\n\n### Grant the required security permission\n\nOpenShift enforces strict security policies called **Security Context Constraints (SCCs)**. By default, pods can't run with a specific user ID. The n8n chart runs as user ID `1000`, so you must explicitly allow this.\n\nUse the full explicit form. The shorthand `-z` flag can silently fail in some OpenShift versions:\n\n```\noc adm policy add-scc-to-user anyuid \\\n system:serviceaccount:$NAMESPACE:n8n\n```\n\nVerify the binding was created:\n\n```\noc get rolebindings -n $NAMESPACE\n```\n\nYou should see a binding referencing `system:openshift:scc:anyuid`.\n\n### Create the required secret\n\n```\noc create secret generic n8n-secrets \\\n --namespace $NAMESPACE \\\n --from-literal=N8N_ENCRYPTION_KEY=\"$(openssl rand -hex 32)\" \\\n --from-literal=N8N_HOST=\"localhost\" \\\n --from-literal=N8N_PORT=\"5678\" \\\n --from-literal=N8N_PROTOCOL=\"http\"\n```\n\n**Back up the encryption key immediately:**\n\n```\noc get secret n8n-secrets -n $NAMESPACE \\\n -o jsonpath='{.data.N8N_ENCRYPTION_KEY}' | base64 --decode\n```\n\nCopy that output and store it somewhere safe. Losing it means all stored credentials in your workflows become permanently unreadable.\n\n### Create your values file\n\nCreate a file called `n8n-standalone-values.yaml`. You can use `nano` (a simple text editor):\n\n```\nnano n8n-standalone-values.yaml\n```\n\nPaste the following, then press `Ctrl+O` to save and `Ctrl+X` to exit:\n\n```\n# n8n-standalone-values.yaml\n# Single pod, SQLite database, no external dependencies.\n\nqueueMode:\n enabled: false\n\ndatabase:\n type: sqlite\n useExternal: false\n\nredis:\n enabled: false\n\n# PVC stores the SQLite database file.\npersistence:\n enabled: true\n size: 5Gi\n # No storageClassName needed — CRC provides a default storage provisioner.\n\nsecretRefs:\n existingSecret: \"n8n-secrets\"\n\nservice:\n type: ClusterIP\n port: 5678\n\n# OpenShift: securityContext must be enabled so the pod runs as UID 1000 (node user)\n# with fsGroup 1000 (so the PVC is writable). The anyuid SCC granted above\n# allows this. The seccompProfile line is removed from the chart template in\n# \"Deploy n8n\" because OpenShift 4.14+ rejects it even with anyuid.\nsecurityContext:\n enabled: true\n\nresources:\n main:\n requests:\n cpu: 100m\n memory: 256Mi\n limits:\n cpu: \"1\"\n memory: 1Gi\n\nconfig:\n timezone: UTC\n```\n\n### Deploy n8n\n\nThe n8n Helm chart hard codes `seccompProfile: RuntimeDefault` in the pod spec. OpenShift 4.14+ converts this to a deprecated alpha annotation that's rejected at admission, even when `anyuid` SCC is granted. The fix is to pull the chart locally, remove those two lines, and install from the patched copy.\n\n**Pull and patch the chart:**\n\n```\nhelm pull oci://ghcr.io/n8n-io/n8n-helm-chart/n8n --version 1.0.3 --untar\nsed -i '/seccompProfile:/d; /type: RuntimeDefault/d' ~/n8n/templates/deployment-main.yaml\n\n# Confirm the lines are gone (should return no output)\ngrep -n \"seccomp\\|RuntimeDefault\" ~/n8n/templates/deployment-main.yaml\n```\n\n**Install from the patched chart:**\n\n```\nhelm install n8n ~/n8n/ \\\n --namespace $NAMESPACE \\\n --values n8n-standalone-values.yaml \\\n --wait \\\n --timeout 10m\n```\n\n### Access n8n using port forward\n\nOpenShift Routes require a hostname, which adds complexity for standalone local access. Port-forward is simpler:\n\n```\noc port-forward service/n8n-main --namespace $NAMESPACE 5678:5678\n```\n\nLeave this running, then open your browser to:\n\n```\nhttp://localhost:5678\n```\n\nn8n will prompt you to create an owner account.\n\nStop tunnel\n\nPress `Ctrl+C` to stop the tunnel. Re-run the `port-forward` command to access n8n again later.\n\n### Check deployment status\n\n```\noc get pods -n $NAMESPACE\n```\n\nExpected:\n\n```\nNAME READY STATUS RESTARTS AGE\nn8n-main-7d9f8b-xxxx 1/1 Running 0 3m\n```\n\n**Standalone deployment complete.**\n\n## Multi-instance queue mode\n\nMulti-instance queue mode runs multiple n8n pods with a shared database, message queue, and object storage. It requires an [n8n Enterprise license](https://n8n.io/pricing/).\n\nInstead of AWS managed services, this guide uses in-cluster equivalents that mirror what you would find in an on-premises or customer OpenShift environment:\n\n| AWS Service | Local Equivalent |\n| ----------------- | ----------------------------------------- |\n| RDS PostgreSQL | PostgreSQL (Bitnami Helm chart) |\n| ElastiCache Redis | Redis (Bitnami Helm chart) |\n| S3 | MinIO (S3-compatible, Bitnami Helm chart) |\n\n### Install in-cluster services\n\n#### Create the Project and add Bitnami Helm repo\n\n```\noc new-project $NAMESPACE\n```\n\nAdd the Bitnami chart repository (only needed once):\n\n```\nhelm repo add bitnami https://charts.bitnami.com/bitnami\nhelm repo update\n```\n\n#### Install PostgreSQL\n\nIn the command below, replace `YourStrongPassword123` with a suitable complex password.\n\n```\nhelm install postgresql bitnami/postgresql \\\n --namespace $NAMESPACE \\\n --set auth.username=n8n \\\n --set auth.password='YourStrongPassword123' \\\n --set auth.database=n8n_enterprise \\\n --set global.compatibility.openshift.adaptSecurityContext=auto \\\n --wait\n```\n\nFlag\n\nThe `global.compatibility.openshift.adaptSecurityContext=auto` flag tells Bitnami to let OpenShift assign the correct user ID automatically (avoids SCC errors).\n\nSave the endpoint, as it's fixed for in-cluster services:\n\n```\npostgresql.YOUR_NAMESPACE.svc.cluster.local\n```\n\nReplace `YOUR_NAMESPACE` with your actual `$NAMESPACE` value (e.g. `n8n-20260306`).\n\n#### Install Redis\n\n```\nhelm install redis bitnami/redis \\\n --namespace $NAMESPACE \\\n --set auth.enabled=false \\\n --set architecture=standalone \\\n --set global.compatibility.openshift.adaptSecurityContext=auto \\\n --wait\n```\n\nRedis endpoint: `redis-master.$NAMESPACE.svc.cluster.local`\n\n#### Install MinIO (S3-compatible storage)\n\nIn the command below, replace `MinioStrongPassword123` with a suitable complex password.\n\n```\nhelm install minio bitnami/minio \\\n --namespace $NAMESPACE \\\n --set auth.rootUser=minioadmin \\\n --set auth.rootPassword='MinioStrongPassword123' \\\n --set global.compatibility.openshift.adaptSecurityContext=auto \\\n --wait\n```\n\nMinIO endpoint: `http://minio:9000` (within the same namespace, just the service name works)\n\n#### Create the n8n storage bucket in MinIO\n\nMinIO needs a bucket created before n8n can use it. Use the MinIO web console:\n\n**Open the MinIO console:**\n\n```\noc port-forward svc/minio 9001:9001 -n $NAMESPACE\n```\n\nLeave this running, then open your browser to `http://localhost:9001`.\n\nLog in with:\n\n- **Username:** `minioadmin`\n- **Password:** `MinioStrongPassword123`\n\nIn the console:\n\n1. Click **Buckets** in the left sidebar → **Create Bucket**\n1. **Bucket Name:** `n8n-data`\n1. Click **Create Bucket**\n\nGo back to the terminal and press `Ctrl+C` to stop the port-forward.\n\n### Deploy n8n\n\n#### Grant SCC for n8n\n\n```\noc adm policy add-scc-to-user anyuid \\\n system:serviceaccount:$NAMESPACE:n8n-enterprise\n```\n\nVerify that `oc get rolebindings -n $NAMESPACE` shows a binding for `system:openshift:scc:anyuid`.\n\n#### Create required secrets\n\n```\n# Core n8n secrets\noc create secret generic n8n-enterprise-secrets \\\n --namespace $NAMESPACE \\\n --from-literal=N8N_ENCRYPTION_KEY=\"$(openssl rand -hex 32)\" \\\n --from-literal=N8N_HOST=\"localhost\" \\\n --from-literal=N8N_PORT=\"5678\" \\\n --from-literal=N8N_PROTOCOL=\"http\"\n```\n\n**Back up the encryption key immediately:**\n\n```\noc get secret n8n-enterprise-secrets -n $NAMESPACE \\\n -o jsonpath='{.data.N8N_ENCRYPTION_KEY}' | base64 --decode\n```\n\nStore that value somewhere safe.\n\nIn the commands below, replace `YourStrongPassword123` and `MinioStrongPassword123` with the passwords from the earlier steps.\n\n```\n# Database password (must match what you set when installing PostgreSQL)\noc create secret generic n8n-enterprise-db-secret \\\n --namespace $NAMESPACE \\\n --from-literal=password='YourStrongPassword123'\n\n# MinIO credentials\noc create secret generic n8n-minio-secret \\\n --namespace $NAMESPACE \\\n --from-literal=root-password='MinioStrongPassword123'\n```\n\n#### Create values file\n\nCreate `n8n-multimain-ocp-values.yaml`. Replace the **3 placeholder values** marked `# <-- REPLACE`:\n\n```\nnano n8n-multimain-ocp-values.yaml\n```\n\n```\n# n8n-multimain-ocp-values.yaml\n# Multi-instance queue mode for OpenShift Local (CRC).\n# Uses in-cluster PostgreSQL, Redis, and MinIO instead of AWS services.\n# Requires Enterprise license.\n\n# --- Enterprise license ---\nlicense:\n enabled: true\n activationKey: \"your-enterprise-license-key-here\" # <-- REPLACE\n\n# --- Multi-main: 2 replicas (reduced for local resources) ---\nmultiMain:\n enabled: true\n replicas: 2\n\n# --- Queue mode: 2 worker pods ---\nqueueMode:\n enabled: true\n workerReplicaCount: 2\n workerConcurrency: 5\n\n# --- Webhook processors ---\nwebhookProcessor:\n enabled: true\n replicaCount: 1\n disableProductionWebhooksOnMainProcess: true\n\n# --- PostgreSQL (in-cluster) ---\ndatabase:\n type: postgresdb\n useExternal: true\n host: \"postgresql.YOUR_NAMESPACE.svc.cluster.local\" # <-- REPLACE YOUR_NAMESPACE\n port: 5432\n database: n8n_enterprise\n schema: \"public\"\n user: n8n\n passwordSecret:\n name: \"n8n-enterprise-db-secret\"\n key: \"password\"\n\n# --- Redis (in-cluster, no TLS) ---\nredis:\n enabled: true\n useExternal: true\n host: \"redis-master.YOUR_NAMESPACE.svc.cluster.local\" # <-- REPLACE YOUR_NAMESPACE\n port: 6379\n tls: false\n\n# --- MinIO (S3-compatible, in-cluster) ---\ns3:\n enabled: true\n bucket:\n name: \"n8n-data\"\n region: \"us-east-1\"\n host: \"http://minio:9000\"\n auth:\n autoDetect: false\n accessKeyId: \"minioadmin\"\n secretAccessKeySecret:\n name: \"n8n-minio-secret\"\n key: \"root-password\"\n storage:\n mode: \"s3\"\n availableModes: \"filesystem,s3\"\n forcePathStyle: true\n\n# --- Service account ---\nserviceAccount:\n create: true\n name: n8n\n```\n\nSave and exit nano (`Ctrl+O`, `Ctrl+X`).\n\n**Before deploying**, replace the two `YOUR_NAMESPACE` placeholders with your actual namespace value:\n\n```\n# Check your namespace value\necho $NAMESPACE\n\n# Replace in the file (this edits it automatically)\nsed -i \"s/YOUR_NAMESPACE/$NAMESPACE/g\" n8n-multimain-ocp-values.yaml\n```\n\nVerify the replacements:\n\n```\ngrep \"svc.cluster.local\" n8n-multimain-ocp-values.yaml\n```\n\nBoth lines should show your actual namespace name, not `YOUR_NAMESPACE`.\n\n#### Deploy n8n\n\nIf you didn't patch the chart previously, pull and patch it now:\n\n```\nhelm pull oci://ghcr.io/n8n-io/n8n-helm-chart/n8n --version 1.0.3 --untar\nsed -i '/seccompProfile:/d; /type: RuntimeDefault/d' ~/n8n/templates/deployment-main.yaml\ngrep -n \"seccomp\\|RuntimeDefault\" ~/n8n/templates/deployment-main.yaml # should return nothing\n```\n\nInstall from the patched chart:\n\n```\nhelm install n8n ~/n8n/ \\\n --namespace $NAMESPACE \\\n --values n8n-multimain-ocp-values.yaml \\\n --wait \\\n --timeout 15m\n```\n\n#### Create a route for external access\n\nIn OpenShift, a **Route** exposes a service to the outside world. It's the equivalent of a Kubernetes Ingress or LoadBalancer, and requires no extra controller:\n\n```\noc expose svc/n8n-main -n $NAMESPACE\n```\n\nGet the URL:\n\n```\nexport ROUTE=$(oc get route n8n-main -n $NAMESPACE -o jsonpath='{.spec.host}')\necho \"n8n URL: http://$ROUTE\"\n```\n\nThe URL will look like: `http://n8n-main-n8n-20260306.apps-crc.testing`\n\n#### Update the host secret\n\nn8n needs to know its public URL. Update the secret with the Route hostname, then restart the pods:\n\n```\nENCRYPTION_KEY=$(oc get secret n8n-enterprise-secrets -n $NAMESPACE \\\n -o jsonpath='{.data.N8N_ENCRYPTION_KEY}' | base64 --decode)\n\noc create secret generic n8n-enterprise-secrets \\\n --namespace $NAMESPACE \\\n --from-literal=N8N_ENCRYPTION_KEY=\"$ENCRYPTION_KEY\" \\\n --from-literal=N8N_HOST=\"$ROUTE\" \\\n --from-literal=N8N_PORT=\"5678\" \\\n --from-literal=N8N_PROTOCOL=\"http\" \\\n --dry-run=client -o yaml | oc apply -f -\n\noc rollout restart deployment -n $NAMESPACE\n```\n\nWait for the rollout to complete:\n\n```\noc rollout status deployment/n8n-main -n $NAMESPACE\n```\n\n#### Verify all pods are running\n\n```\noc get pods -n $NAMESPACE\n```\n\nExpected (all `Running`):\n\n```\nNAME READY STATUS RESTARTS AGE\nn8n-main-xxxx-aaaa 1/1 Running 0 5m\nn8n-main-xxxx-bbbb 1/1 Running 0 5m\nn8n-worker-xxxx-aaaa 1/1 Running 0 5m\nn8n-worker-xxxx-bbbb 1/1 Running 0 5m\nn8n-webhook-processor-xxxx-aaaa 1/1 Running 0 5m\npostgresql-0 1/1 Running 0 15m\nredis-master-0 1/1 Running 0 15m\nminio-xxxx-xxxx 1/1 Running 0 15m\n```\n\nOpen your browser to the URL printed above.\n\n**Multi-instance deployment complete.**\n\n## Updating n8n\n\nTo change configuration or upgrade the chart version, pull and re-patch the new chart version, then upgrade:\n\n```\n# Remove the old local chart copy\nrm -rf ~/n8n/\n\n# Pull and patch the new version\nhelm pull oci://ghcr.io/n8n-io/n8n-helm-chart/n8n --version <new-version> --untar\nsed -i '/seccompProfile:/d; /type: RuntimeDefault/d' ~/n8n/templates/deployment-main.yaml\n\n# Standalone\nhelm upgrade n8n ~/n8n/ \\\n --namespace $NAMESPACE \\\n --values n8n-standalone-values.yaml\n\n# Multi-instance\nhelm upgrade n8n ~/n8n/ \\\n --namespace $NAMESPACE \\\n --values n8n-multimain-ocp-values.yaml\n```\n\n## Stopping and resuming CRC\n\nCRC doesn't need to be deleted between sessions. You can stop and restart it:\n\n```\n# Stop the cluster (saves state)\ncrc stop\n\n# Start it again later\ncrc start\n```\n\nAfter restarting, re-run:\n\n```\neval $(crc oc-env)\nexport NAMESPACE=n8n-YYYYMMDD # use your original date\noc login -u kubeadmin -p <password> https://api.crc.testing:6443\n```\n\n## Troubleshooting\n\n### `crc setup` fails with “libvirt not found”\n\n```\nsudo apt install -y qemu-kvm libvirt-daemon-system libvirt-clients\nsudo systemctl start libvirtd\n```\n\nThen re-run `crc setup`.\n\n### `crc start` fails with “insufficient memory”\n\nCRC requires at least 9 GB of free RAM. Close other applications and try again. If you [followed instructions for configuring CRC memory](#configure-crc-memory-and-start-the-cluster), CRC is configured to use 14 GB.\n\n### n8n pod stuck in `Pending` or never created SCC error\n\nCheck events for the error:\n\n```\noc get events -n $NAMESPACE --sort-by='.lastTimestamp' | tail -20\n```\n\nIf you see `unable to validate against any security context constraint` or `seccomp may not be set`, the chart’s hard coded `seccompProfile: RuntimeDefault` is being rejected. OpenShift 4.14+ converts this to a deprecated alpha annotation that admission rejects even when `anyuid` SCC is granted.\n\n**1. Grant anyuid using the explicit form** (the `-z` shorthand can silently fail):\n\n```\n# For standalone\noc adm policy add-scc-to-user anyuid \\\n system:serviceaccount:$NAMESPACE:n8n\n\n# For multi-instance\noc adm policy add-scc-to-user anyuid \\\n system:serviceaccount:$NAMESPACE:n8n-enterprise\n```\n\nVerify: run `oc get rolebindings -n $NAMESPACE`. You should see a binding for `system:openshift:scc:anyuid`.\n\n**2. Pull the chart locally and remove the `seccompProfile` lines:**\n\n```\nhelm pull oci://ghcr.io/n8n-io/n8n-helm-chart/n8n --version 1.0.3 --untar\nsed -i '/seccompProfile:/d; /type: RuntimeDefault/d' ~/n8n/templates/deployment-main.yaml\n\n# Confirm they're gone (should return no output)\ngrep -n \"seccomp\\|RuntimeDefault\" ~/n8n/templates/deployment-main.yaml\n```\n\n**3. Uninstall and reinstall from the patched chart:**\n\n```\nhelm uninstall n8n -n $NAMESPACE\nhelm install n8n ~/n8n/ \\\n --namespace $NAMESPACE \\\n --values n8n-standalone-values.yaml \\\n --wait \\\n --timeout 10m\n```\n\n### Route URL returns “Application not available”\n\nThe pods may still be starting. Check:\n\n```\noc get pods -n $NAMESPACE\noc rollout status deployment/n8n-main -n $NAMESPACE\n```\n\nAlso confirm the Route exists:\n\n```\noc get route -n $NAMESPACE\n```\n\n### n8n pod stuck in `Pending` with `Insufficient memory`\n\nThe CRC node doesn’t have enough free memory to schedule the pod.\n\n**Fix:** Increase CRC’s VM memory and restart:\n\n```\ncrc stop\ncrc config set memory 14336\ncrc start\n```\n\nAfter CRC restarts, the pod should schedule automatically. If the pod is still pending after a few minutes, delete it to force a reschedule:\n\n```\noc delete pod -n $NAMESPACE -l app.kubernetes.io/component=main\n```\n\nIf your machine can’t spare 14 GB, you can also lower the pod’s memory request in `n8n-standalone-values.yaml`:\n\n```\nresources:\n main:\n requests:\n memory: 256Mi\n```\n\nThen upgrade: `helm upgrade n8n ~/n8n/ -n $NAMESPACE -f n8n-standalone-values.yaml`\n\n### DNS not resolving `.apps-crc.testing` or `api.crc.testing`\n\nOn Ubuntu, CRC configures DNS automatically. If it fails, restart NetworkManager:\n\n```\nsudo systemctl restart NetworkManager\n```\n\nIf still broken, add entries manually (CRC routes traffic through `127.0.0.1`):\n\n```\nsudo tee -a /etc/hosts <<EOF\n127.0.0.1 api.crc.testing\n127.0.0.1 console-openshift-console.apps-crc.testing\n127.0.0.1 oauth-openshift.apps-crc.testing\n127.0.0.1 default-route-openshift-image-registry.apps-crc.testing\nEOF\n```\n\nSubdomains\n\nWhen you expose Routes in the multi-instance section, new `*.apps-crc.testing` subdomains are created. Add them to `/etc/hosts` pointing to `127.0.0.1` if your browser can’t reach them.\n\n### n8n pod crashes with `EACCES: permission denied` writing to `/home/node/.n8n/`\n\nThis means the pod is running as a random OpenShift-assigned UID instead of UID 1000 (the `node` user the n8n image expects). It happens when `securityContext.enabled: false` is set in values without `runAsUser: 1000` and `fsGroup: 1000`, OpenShift assigns a random UID that can’t write to the PVC.\n\n**Fix:** Ensure `securityContext.enabled: true` is set in your values file, and that the chart has been patched to remove `seccompProfile` (see the SCC error section above). Both are required together.\n\n### View pod logs\n\n```\n# Main process\noc logs -n $NAMESPACE -l app.kubernetes.io/component=main --tail=50\n\n# Workers\noc logs -n $NAMESPACE -l app.kubernetes.io/component=worker --tail=50\n\n# Webhook processors\noc logs -n $NAMESPACE -l app.kubernetes.io/component=webhook-processor --tail=50\n```\n\n### All events in the namespace\n\n```\noc get events -n $NAMESPACE --sort-by='.lastTimestamp'\n```\n\n## Quick Reference\n\n### Re-export variables after reopening terminal\n\n```\neval $(crc oc-env)\nexport NAMESPACE=n8n-YYYYMMDD # use the date from your original deployment\noc login -u kubeadmin -p <password> https://api.crc.testing:6443\n```\n\n### Check cluster status\n\n```\ncrc status\n```\n\n### Open the OpenShift web console\n\n```\ncrc console\n```\n\nLog in with `kubeadmin` / your password to see a graphical view of everything running.\n\n### Things to save\n\n| Item | Why it matters |\n| ------------------------------- | --------------------------------------------- |\n| `kubeadmin` password | Log in to the cluster |\n| n8n encryption key | Lose this = all stored credentials unreadable |\n| `n8n-standalone-values.yaml` | Required for `helm upgrade` |\n| `n8n-multimain-ocp-values.yaml` | Required for `helm upgrade` |\n| MinIO root password | Access the MinIO console |\n| PostgreSQL password | Database access |\n\n## Next steps\n\n- Learn more about [configuring](../../../configuration/environment-variables/) and [scaling](../../../scaling/overview/) n8n.\n- Or explore using n8n: try the [Quickstarts](../../../../try-it-out/).\n",
18068
+ "markdown": "# Hosting n8n on OpenShift Local (CRC)\n\nThis guide walks you through deploying n8n on OpenShift Local (CRC), Red Hat's tool for running a local OpenShift cluster. It mirrors AWS/EKS deployment, but runs entirely on your local machine. It's designed for testing n8n in an OpenShift environment locally, without cloud costs.\n\nYou will need a machine with significant resources available, given how many resources OpenShift itself consumes.\n\n## OpenShift concepts vs standard Kubernetes\n\nOpenShift is built on Kubernetes but uses different terminology and has stricter security defaults. If you are familiar with standard Kubernetes, or with a guide that targets a managed Kubernetes service such as EKS, the table below maps the equivalent concepts so you know what to expect.\n\n| Standard Kubernetes / EKS | OpenShift Local (CRC) |\n| ---------------------------- | --------------------------------------------------------- |\n| `kubectl` | `oc` (OpenShift CLI; also understands `kubectl` commands) |\n| Namespace | Project (same concept, different command) |\n| Ingress / LoadBalancer | Route (built into OpenShift, no controller needed) |\n| EBS StorageClass (gp3) | CRC built-in storage provisioner (no setup needed) |\n| RDS PostgreSQL | In-cluster PostgreSQL via Helm (Bitnami) |\n| ElastiCache Redis | In-cluster Redis via Helm (Bitnami) |\n| AWS S3 | MinIO in-cluster (S3-compatible) |\n| Pod Identity / IRSA | Access keys via Kubernetes Secret |\n| AWS Load Balancer Controller | Not needed (Routes are built-in) |\n| OIDC / IAM | Not needed |\n| ~$135–400/month | Free (runs on your machine) |\n\n## Prerequisites\n\nBefore starting, confirm your machine has:\n\n- **CPU**: 4 or more physical cores (not just threads) with virtualization support\n- **RAM**: 32+ GB free minimum (CRC reserves 9 GB for its VM)\n- **Disk**: 100 GB free\n- **OS**: Ubuntu (22.04 LTS or newer)\n\n## Prepare Ubuntu\n\n### Open a terminal\n\nPress `Ctrl+Alt+T` or search for **Terminal** in the Applications menu.\n\nEvery command in this guide is typed into the terminal and run by pressing **Enter**.\n\n### Update your system\n\nStart with a system update to avoid dependency issues:\n\n```\nsudo apt update && sudo apt upgrade -y\n```\n\nsudo\n\n`sudo` means “run as administrator”. You will be prompted for your password. Characters you type won't appear on screen, this is normal.\n\n### Check CPU virtualization support\n\nCRC runs a virtual machine. Your CPU must support hardware virtualization:\n\n```\negrep -c '(vmx|svm)' /proc/cpuinfo\n```\n\n- **Output `0`**: Virtualization is disabled. Enter your BIOS/UEFI settings and enable VT-x (Intel) or AMD-V (AMD), then reboot and try again.\n- **Output `1` or higher**: You are good to continue.\n\n### Install KVM and libvirt\n\nKVM is Linux’s built-in hypervisor. CRC uses it to run the OpenShift cluster VM:\n\n```\nsudo apt install -y qemu-kvm libvirt-daemon-system libvirt-clients bridge-utils\n```\n\nInstall `virtiofsd`, which CRC requires to share the filesystem with the cluster VM:\n\n```\nsudo apt install -y virtiofsd\n```\n\nStart the libvirt service and configure it to start automatically on boot:\n\n```\nsudo systemctl start libvirtd\nsudo systemctl enable libvirtd\n```\n\nVerify it's running:\n\n```\nsudo systemctl status libvirtd\n```\n\nLook for `Active: active (running)` in green. Press `q` to exit.\n\n### Add user to required groups\n\nThis allows you to use KVM and libvirt without typing `sudo` for every command:\n\n```\nsudo usermod -aG libvirt $USER\nsudo usermod -aG kvm $USER\n```\n\nWarning\n\n**You must log out and log back in (or reboot) for this to take effect.** If you skip this step, CRC will fail with a “permission denied” error.\n\nReboot now:\n\n```\nsudo reboot\n```\n\nAfter logging back in, open a terminal and verify group membership:\n\n```\ngroups\n```\n\nYou should see `libvirt` and `kvm` listed.\n\n### Install NetworkManager\n\nCRC requires NetworkManager to manage DNS entries for the cluster’s internal domains (`*.apps-crc.testing`, `api.crc.testing`):\n\n```\nsudo apt install -y network-manager\nsudo systemctl start NetworkManager\nsudo systemctl enable NetworkManager\n```\n\nVerify it's connected:\n\n```\nnmcli general status\n```\n\nThe `STATE` column should show `connected`.\n\n## Install tools\n\n### Get a Red Hat account and pull secret\n\nCRC requires a free Red Hat account to pull container images.\n\n1. [Create a free Red Hat account](https://console.redhat.com/), if you don't already have one.\n1. In [console.redhat.com/openshift/create/local](https://console.redhat.com/openshift/create/local), click **Download OpenShift Local**.\n1. Select **Linux**, and download the `.tar.xz` file to `~/Downloads`.\n1. On the same page of the Red Hat console, click **Copy pull secret**. Paste it into a text file and save it for later.\n\n### Install CRC\n\nOpen a terminal in your Downloads folder.\n\n```\ncd ~/Downloads\n```\n\nExtract the archive.\n\n```\ntar xf crc-linux-amd64.tar.xz\n```\n\nMove the `crc` binary to a system-wide location, so it's available in any terminal:\n\n```\nsudo mv crc-*-linux-amd64/crc /usr/local/bin/\n```\n\nVerify the installation:\n\n```\ncrc version\n```\n\nA version number should print to the terminal.\n\n### Install Helm\n\nHelm installs n8n and supporting services into the cluster:\n\n```\ncurl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash\n```\n\nVerify:\n\n```\nhelm version\n```\n\n### Set environment variables\n\n```\nexport NAMESPACE=n8n-$(date +%Y%m%d)\necho \"Namespace:$NAMESPACE\"\n```\n\nVariable persistence\n\nThese variables only last for the current terminal session. Re-run this line whenever you open a new terminal before continuing.\n\n## Start OpenShift Local\n\n### Run CRC setup\n\nYou only need to run this once. It configures KVM networking, checks system requirements, and downloads the CRC bundle (~2.5 GB):\n\n```\ncrc setup\n```\n\nThis takes several minutes. If it reports any missing packages, install them with `sudo apt install -y <package-name>` and re-run.\n\n### Configure CRC memory and start the cluster\n\nCRC defaults to 9 GB of RAM for its VM. n8n and its supporting services need more headroom. Set the memory to 14 GB before starting:\n\n```\ncrc config set memory 14336\n```\n\nYou only need to run this once. The setting persists across `crc stop` / `crc start` cycles.\n\n**Recommended:** Save your pull secret to a file first so you don’t have to paste it every time:\n\n```\n# Open the file, paste your pull secret (from earlier), then Ctrl+O to save, Ctrl+X to exit\nnano ~/pull-secret.txt\n\n# Restrict permissions so only you can read it\nchmod 600 ~/pull-secret.txt\n```\n\nStart CRC using the file:\n\n```\ncrc start --pull-secret-file ~/pull-secret.txt\n```\n\nAlternatively, run `crc start` without the flag and paste the secret when prompted.\n\n**This takes 10–15 minutes.** When complete you will see something like:\n\n```\nStarted the OpenShift cluster.\n\nThe server is accessible via web console at:\n https://console-openshift-console.apps-crc.testing\n\nLog in as administrator:\n Username: kubeadmin\n Password: <generated-password>\n\nLog in as user:\n Username: developer\n Password: developer\n```\n\n**Save the `kubeadmin` password now.** You will need it in the next step. You can retrieve it later using `crc console --credentials`.\n\n### Verify DNS resolution\n\nOn Ubuntu, CRC configures the system resolver automatically with NetworkManager and systemd-resolved. No manual `/etc/hosts` entries are needed.\n\nVerify the API is reachable:\n\n```\nsudo ss -tlnp | grep 6443\n```\n\nYou should see a process bound to `127.0.0.1:6443`. If nothing appears, re-run `crc start`. If DNS doesn't resolve `*.apps-crc.testing`, see the troubleshooting section.\n\n### Configure your shell\n\nCRC bundles the `oc` CLI inside the VM. This command makes it available in your terminal:\n\n```\neval $(crc oc-env)\n```\n\nTo make this permanent so you don't have to run it every time you open a terminal:\n\n```\necho 'eval $(crc oc-env)' >> ~/.bashrc\nsource ~/.bashrc\n```\n\nVerify `oc` works:\n\n```\noc version\n```\n\n### Log in to the cluster\n\n```\noc login -u kubeadmin -p <your-kubeadmin-password> https://api.crc.testing:6443\n```\n\nReplace `<your-kubeadmin-password>` with the password printed when you [configured CRC memory and started the cluster](#configure-crc-memory-and-start-the-cluster).\n\nVerify you are logged in:\n\n```\noc whoami\n```\n\n`kubeadmin` should print to the screen.\n\n## Standalone deployment\n\nStandalone mode runs n8n as a single pod with SQLite. No external database or Redis is required. This is ideal for exploring n8n and testing workflows locally.\n\n### Create the project\n\nIn OpenShift, a **project** is the same as a Kubernetes namespace: an isolated space for your resources:\n\n```\noc new-project $NAMESPACE\n```\n\n### Grant the required security permission\n\nOpenShift enforces strict security policies called **Security Context Constraints (SCCs)**. By default, pods can't run with a specific user ID. The n8n chart runs as user ID `1000`, so you must explicitly allow this.\n\nUse the full explicit form. The shorthand `-z` flag can silently fail in some OpenShift versions:\n\n```\noc adm policy add-scc-to-user anyuid \\\n system:serviceaccount:$NAMESPACE:n8n\n```\n\nVerify the binding was created:\n\n```\noc get rolebindings -n $NAMESPACE\n```\n\nYou should see a binding referencing `system:openshift:scc:anyuid`.\n\n### Create the required secret\n\n```\noc create secret generic n8n-secrets \\\n --namespace $NAMESPACE \\\n --from-literal=N8N_ENCRYPTION_KEY=\"$(openssl rand -hex 32)\" \\\n --from-literal=N8N_HOST=\"localhost\" \\\n --from-literal=N8N_PORT=\"5678\" \\\n --from-literal=N8N_PROTOCOL=\"http\"\n```\n\n**Back up the encryption key immediately:**\n\n```\noc get secret n8n-secrets -n $NAMESPACE \\\n -o jsonpath='{.data.N8N_ENCRYPTION_KEY}' | base64 --decode\n```\n\nCopy that output and store it somewhere safe. Losing it means all stored credentials in your workflows become permanently unreadable.\n\n### Create your values file\n\nCreate a file called `n8n-standalone-values.yaml`. You can use `nano` (a simple text editor):\n\n```\nnano n8n-standalone-values.yaml\n```\n\nPaste the following, then press `Ctrl+O` to save and `Ctrl+X` to exit:\n\n```\n# n8n-standalone-values.yaml\n# Single pod, SQLite database, no external dependencies.\n\nqueueMode:\n enabled: false\n\ndatabase:\n type: sqlite\n useExternal: false\n\nredis:\n enabled: false\n\n# PVC stores the SQLite database file.\npersistence:\n enabled: true\n size: 5Gi\n # No storageClassName needed — CRC provides a default storage provisioner.\n\nsecretRefs:\n existingSecret: \"n8n-secrets\"\n\nservice:\n type: ClusterIP\n port: 5678\n\n# OpenShift: securityContext must be enabled so the pod runs as UID 1000 (node user)\n# with fsGroup 1000 (so the PVC is writable). The anyuid SCC granted above\n# allows this. The seccompProfile line is removed from the chart template in\n# \"Deploy n8n\" because OpenShift 4.14+ rejects it even with anyuid.\nsecurityContext:\n enabled: true\n\nresources:\n main:\n requests:\n cpu: 100m\n memory: 256Mi\n limits:\n cpu: \"1\"\n memory: 1Gi\n\nconfig:\n timezone: UTC\n```\n\n### Deploy n8n\n\nThe n8n Helm chart hard codes `seccompProfile: RuntimeDefault` in the pod spec. OpenShift 4.14+ converts this to a deprecated alpha annotation that's rejected at admission, even when `anyuid` SCC is granted. The fix is to pull the chart locally, remove those two lines, and install from the patched copy.\n\n**Pull and patch the chart:**\n\n```\nhelm pull oci://ghcr.io/n8n-io/n8n-helm-chart/n8n --version 1.0.3 --untar\nsed -i '/seccompProfile:/d; /type: RuntimeDefault/d' ~/n8n/templates/deployment-main.yaml\n\n# Confirm the lines are gone (should return no output)\ngrep -n \"seccomp\\|RuntimeDefault\" ~/n8n/templates/deployment-main.yaml\n```\n\n**Install from the patched chart:**\n\n```\nhelm install n8n ~/n8n/ \\\n --namespace $NAMESPACE \\\n --values n8n-standalone-values.yaml \\\n --wait \\\n --timeout 10m\n```\n\n### Access n8n using port forward\n\nOpenShift Routes require a hostname, which adds complexity for standalone local access. Port-forward is simpler:\n\n```\noc port-forward service/n8n-main --namespace $NAMESPACE 5678:5678\n```\n\nLeave this running, then open your browser to:\n\n```\nhttp://localhost:5678\n```\n\nn8n will prompt you to create an owner account.\n\nStop tunnel\n\nPress `Ctrl+C` to stop the tunnel. Re-run the `port-forward` command to access n8n again later.\n\n### Check deployment status\n\n```\noc get pods -n $NAMESPACE\n```\n\nExpected:\n\n```\nNAME READY STATUS RESTARTS AGE\nn8n-main-7d9f8b-xxxx 1/1 Running 0 3m\n```\n\n**Standalone deployment complete.**\n\n## Multi-instance queue mode\n\nMulti-instance queue mode runs multiple n8n pods with a shared database, message queue, and object storage. It requires an [n8n Enterprise license](https://n8n.io/pricing/).\n\nInstead of AWS managed services, this guide uses in-cluster equivalents that mirror what you would find in an on-premises or customer OpenShift environment:\n\n| AWS Service | Local Equivalent |\n| ----------------- | ----------------------------------------- |\n| RDS PostgreSQL | PostgreSQL (Bitnami Helm chart) |\n| ElastiCache Redis | Redis (Bitnami Helm chart) |\n| S3 | MinIO (S3-compatible, Bitnami Helm chart) |\n\n### Install in-cluster services\n\n#### Create the Project and add Bitnami Helm repo\n\n```\noc new-project $NAMESPACE\n```\n\nAdd the Bitnami chart repository (only needed once):\n\n```\nhelm repo add bitnami https://charts.bitnami.com/bitnami\nhelm repo update\n```\n\n#### Install PostgreSQL\n\nIn the command below, replace `YourStrongPassword123` with a suitable complex password.\n\n```\nhelm install postgresql bitnami/postgresql \\\n --namespace $NAMESPACE \\\n --set auth.username=n8n \\\n --set auth.password='YourStrongPassword123' \\\n --set auth.database=n8n_enterprise \\\n --set global.compatibility.openshift.adaptSecurityContext=auto \\\n --wait\n```\n\nFlag\n\nThe `global.compatibility.openshift.adaptSecurityContext=auto` flag tells Bitnami to let OpenShift assign the correct user ID automatically (avoids SCC errors).\n\nSave the endpoint, as it's fixed for in-cluster services:\n\n```\npostgresql.YOUR_NAMESPACE.svc.cluster.local\n```\n\nReplace `YOUR_NAMESPACE` with your actual `$NAMESPACE` value (e.g. `n8n-20260306`).\n\n#### Install Redis\n\n```\nhelm install redis bitnami/redis \\\n --namespace $NAMESPACE \\\n --set auth.enabled=false \\\n --set architecture=standalone \\\n --set global.compatibility.openshift.adaptSecurityContext=auto \\\n --wait\n```\n\nRedis endpoint: `redis-master.$NAMESPACE.svc.cluster.local`\n\n#### Install MinIO (S3-compatible storage)\n\nIn the command below, replace `MinioStrongPassword123` with a suitable complex password.\n\n```\nhelm install minio bitnami/minio \\\n --namespace $NAMESPACE \\\n --set auth.rootUser=minioadmin \\\n --set auth.rootPassword='MinioStrongPassword123' \\\n --set global.compatibility.openshift.adaptSecurityContext=auto \\\n --wait\n```\n\nMinIO endpoint: `http://minio:9000` (within the same namespace, just the service name works)\n\n#### Create the n8n storage bucket in MinIO\n\nMinIO needs a bucket created before n8n can use it. Use the MinIO web console:\n\n**Open the MinIO console:**\n\n```\noc port-forward svc/minio 9001:9001 -n $NAMESPACE\n```\n\nLeave this running, then open your browser to `http://localhost:9001`.\n\nLog in with:\n\n- **Username:** `minioadmin`\n- **Password:** `MinioStrongPassword123`\n\nIn the console:\n\n1. Click **Buckets** in the left sidebar → **Create Bucket**\n1. **Bucket Name:** `n8n-data`\n1. Click **Create Bucket**\n\nGo back to the terminal and press `Ctrl+C` to stop the port-forward.\n\n### Deploy n8n\n\n#### Grant SCC for n8n\n\n```\noc adm policy add-scc-to-user anyuid \\\n system:serviceaccount:$NAMESPACE:n8n-enterprise\n```\n\nVerify that `oc get rolebindings -n $NAMESPACE` shows a binding for `system:openshift:scc:anyuid`.\n\n#### Create required secrets\n\n```\n# Core n8n secrets\noc create secret generic n8n-enterprise-secrets \\\n --namespace $NAMESPACE \\\n --from-literal=N8N_ENCRYPTION_KEY=\"$(openssl rand -hex 32)\" \\\n --from-literal=N8N_HOST=\"localhost\" \\\n --from-literal=N8N_PORT=\"5678\" \\\n --from-literal=N8N_PROTOCOL=\"http\"\n```\n\n**Back up the encryption key immediately:**\n\n```\noc get secret n8n-enterprise-secrets -n $NAMESPACE \\\n -o jsonpath='{.data.N8N_ENCRYPTION_KEY}' | base64 --decode\n```\n\nStore that value somewhere safe.\n\nIn the commands below, replace `YourStrongPassword123` and `MinioStrongPassword123` with the passwords from the earlier steps.\n\n```\n# Database password (must match what you set when installing PostgreSQL)\noc create secret generic n8n-enterprise-db-secret \\\n --namespace $NAMESPACE \\\n --from-literal=password='YourStrongPassword123'\n\n# MinIO credentials\noc create secret generic n8n-minio-secret \\\n --namespace $NAMESPACE \\\n --from-literal=root-password='MinioStrongPassword123'\n```\n\n#### Create values file\n\nCreate `n8n-multimain-ocp-values.yaml`. Replace the **3 placeholder values** marked `# <-- REPLACE`:\n\n```\nnano n8n-multimain-ocp-values.yaml\n```\n\n```\n# n8n-multimain-ocp-values.yaml\n# Multi-instance queue mode for OpenShift Local (CRC).\n# Uses in-cluster PostgreSQL, Redis, and MinIO instead of AWS services.\n# Requires Enterprise license.\n\n# --- Enterprise license ---\nlicense:\n enabled: true\n activationKey: \"your-enterprise-license-key-here\" # <-- REPLACE\n\n# --- Multi-main: 2 replicas (reduced for local resources) ---\nmultiMain:\n enabled: true\n replicas: 2\n\n# --- Queue mode: 2 worker pods ---\nqueueMode:\n enabled: true\n workerReplicaCount: 2\n workerConcurrency: 5\n\n# --- Webhook processors ---\nwebhookProcessor:\n enabled: true\n replicaCount: 1\n disableProductionWebhooksOnMainProcess: true\n\n# --- PostgreSQL (in-cluster) ---\ndatabase:\n type: postgresdb\n useExternal: true\n host: \"postgresql.YOUR_NAMESPACE.svc.cluster.local\" # <-- REPLACE YOUR_NAMESPACE\n port: 5432\n database: n8n_enterprise\n schema: \"public\"\n user: n8n\n passwordSecret:\n name: \"n8n-enterprise-db-secret\"\n key: \"password\"\n\n# --- Redis (in-cluster, no TLS) ---\nredis:\n enabled: true\n useExternal: true\n host: \"redis-master.YOUR_NAMESPACE.svc.cluster.local\" # <-- REPLACE YOUR_NAMESPACE\n port: 6379\n tls: false\n\n# --- MinIO (S3-compatible, in-cluster) ---\ns3:\n enabled: true\n bucket:\n name: \"n8n-data\"\n region: \"us-east-1\"\n host: \"http://minio:9000\"\n auth:\n autoDetect: false\n accessKeyId: \"minioadmin\"\n secretAccessKeySecret:\n name: \"n8n-minio-secret\"\n key: \"root-password\"\n storage:\n mode: \"s3\"\n availableModes: \"filesystem,s3\"\n forcePathStyle: true\n\n# --- Service account ---\nserviceAccount:\n create: true\n name: n8n\n```\n\nSave and exit nano (`Ctrl+O`, `Ctrl+X`).\n\n**Before deploying**, replace the two `YOUR_NAMESPACE` placeholders with your actual namespace value:\n\n```\n# Check your namespace value\necho $NAMESPACE\n\n# Replace in the file (this edits it automatically)\nsed -i \"s/YOUR_NAMESPACE/$NAMESPACE/g\" n8n-multimain-ocp-values.yaml\n```\n\nVerify the replacements:\n\n```\ngrep \"svc.cluster.local\" n8n-multimain-ocp-values.yaml\n```\n\nBoth lines should show your actual namespace name, not `YOUR_NAMESPACE`.\n\n#### Deploy n8n\n\nIf you didn't patch the chart previously, pull and patch it now:\n\n```\nhelm pull oci://ghcr.io/n8n-io/n8n-helm-chart/n8n --version 1.0.3 --untar\nsed -i '/seccompProfile:/d; /type: RuntimeDefault/d' ~/n8n/templates/deployment-main.yaml\ngrep -n \"seccomp\\|RuntimeDefault\" ~/n8n/templates/deployment-main.yaml # should return nothing\n```\n\nInstall from the patched chart:\n\n```\nhelm install n8n ~/n8n/ \\\n --namespace $NAMESPACE \\\n --values n8n-multimain-ocp-values.yaml \\\n --wait \\\n --timeout 15m\n```\n\n#### Create a route for external access\n\nIn OpenShift, a **Route** exposes a service to the outside world. It's the equivalent of a Kubernetes Ingress or LoadBalancer, and requires no extra controller:\n\n```\noc expose svc/n8n-main -n $NAMESPACE\n```\n\nGet the URL:\n\n```\nexport ROUTE=$(oc get route n8n-main -n $NAMESPACE -o jsonpath='{.spec.host}')\necho \"n8n URL: http://$ROUTE\"\n```\n\nThe URL will look like: `http://n8n-main-n8n-20260306.apps-crc.testing`\n\n#### Update the host secret\n\nn8n needs to know its public URL. Update the secret with the Route hostname, then restart the pods:\n\n```\nENCRYPTION_KEY=$(oc get secret n8n-enterprise-secrets -n $NAMESPACE \\\n -o jsonpath='{.data.N8N_ENCRYPTION_KEY}' | base64 --decode)\n\noc create secret generic n8n-enterprise-secrets \\\n --namespace $NAMESPACE \\\n --from-literal=N8N_ENCRYPTION_KEY=\"$ENCRYPTION_KEY\" \\\n --from-literal=N8N_HOST=\"$ROUTE\" \\\n --from-literal=N8N_PORT=\"5678\" \\\n --from-literal=N8N_PROTOCOL=\"http\" \\\n --dry-run=client -o yaml | oc apply -f -\n\noc rollout restart deployment -n $NAMESPACE\n```\n\nWait for the rollout to complete:\n\n```\noc rollout status deployment/n8n-main -n $NAMESPACE\n```\n\n#### Verify all pods are running\n\n```\noc get pods -n $NAMESPACE\n```\n\nExpected (all `Running`):\n\n```\nNAME READY STATUS RESTARTS AGE\nn8n-main-xxxx-aaaa 1/1 Running 0 5m\nn8n-main-xxxx-bbbb 1/1 Running 0 5m\nn8n-worker-xxxx-aaaa 1/1 Running 0 5m\nn8n-worker-xxxx-bbbb 1/1 Running 0 5m\nn8n-webhook-processor-xxxx-aaaa 1/1 Running 0 5m\npostgresql-0 1/1 Running 0 15m\nredis-master-0 1/1 Running 0 15m\nminio-xxxx-xxxx 1/1 Running 0 15m\n```\n\nOpen your browser to the URL printed above.\n\n**Multi-instance deployment complete.**\n\n## Updating n8n\n\nTo change configuration or upgrade the chart version, pull and re-patch the new chart version, then upgrade:\n\n```\n# Remove the old local chart copy\nrm -rf ~/n8n/\n\n# Pull and patch the new version\nhelm pull oci://ghcr.io/n8n-io/n8n-helm-chart/n8n --version <new-version> --untar\nsed -i '/seccompProfile:/d; /type: RuntimeDefault/d' ~/n8n/templates/deployment-main.yaml\n\n# Standalone\nhelm upgrade n8n ~/n8n/ \\\n --namespace $NAMESPACE \\\n --values n8n-standalone-values.yaml\n\n# Multi-instance\nhelm upgrade n8n ~/n8n/ \\\n --namespace $NAMESPACE \\\n --values n8n-multimain-ocp-values.yaml\n```\n\n## Stopping and resuming CRC\n\nCRC doesn't need to be deleted between sessions. You can stop and restart it:\n\n```\n# Stop the cluster (saves state)\ncrc stop\n\n# Start it again later\ncrc start\n```\n\nAfter restarting, re-run:\n\n```\neval $(crc oc-env)\nexport NAMESPACE=n8n-YYYYMMDD # use your original date\noc login -u kubeadmin -p <password> https://api.crc.testing:6443\n```\n\n## Troubleshooting\n\n### `crc setup` fails with “libvirt not found”\n\n```\nsudo apt install -y qemu-kvm libvirt-daemon-system libvirt-clients\nsudo systemctl start libvirtd\n```\n\nThen re-run `crc setup`.\n\n### `crc start` fails with “insufficient memory”\n\nCRC requires at least 9 GB of free RAM. Close other applications and try again. If you [followed instructions for configuring CRC memory](#configure-crc-memory-and-start-the-cluster), CRC is configured to use 14 GB.\n\n### n8n pod stuck in `Pending` or never created SCC error\n\nCheck events for the error:\n\n```\noc get events -n $NAMESPACE --sort-by='.lastTimestamp' | tail -20\n```\n\nIf you see `unable to validate against any security context constraint` or `seccomp may not be set`, the chart’s hard coded `seccompProfile: RuntimeDefault` is being rejected. OpenShift 4.14+ converts this to a deprecated alpha annotation that admission rejects even when `anyuid` SCC is granted.\n\n**1. Grant anyuid using the explicit form** (the `-z` shorthand can silently fail):\n\n```\n# For standalone\noc adm policy add-scc-to-user anyuid \\\n system:serviceaccount:$NAMESPACE:n8n\n\n# For multi-instance\noc adm policy add-scc-to-user anyuid \\\n system:serviceaccount:$NAMESPACE:n8n-enterprise\n```\n\nVerify: run `oc get rolebindings -n $NAMESPACE`. You should see a binding for `system:openshift:scc:anyuid`.\n\n**2. Pull the chart locally and remove the `seccompProfile` lines:**\n\n```\nhelm pull oci://ghcr.io/n8n-io/n8n-helm-chart/n8n --version 1.0.3 --untar\nsed -i '/seccompProfile:/d; /type: RuntimeDefault/d' ~/n8n/templates/deployment-main.yaml\n\n# Confirm they're gone (should return no output)\ngrep -n \"seccomp\\|RuntimeDefault\" ~/n8n/templates/deployment-main.yaml\n```\n\n**3. Uninstall and reinstall from the patched chart:**\n\n```\nhelm uninstall n8n -n $NAMESPACE\nhelm install n8n ~/n8n/ \\\n --namespace $NAMESPACE \\\n --values n8n-standalone-values.yaml \\\n --wait \\\n --timeout 10m\n```\n\n### Route URL returns “Application not available”\n\nThe pods may still be starting. Check:\n\n```\noc get pods -n $NAMESPACE\noc rollout status deployment/n8n-main -n $NAMESPACE\n```\n\nAlso confirm the Route exists:\n\n```\noc get route -n $NAMESPACE\n```\n\n### n8n pod stuck in `Pending` with `Insufficient memory`\n\nThe CRC node doesn���t have enough free memory to schedule the pod.\n\n**Fix:** Increase CRC’s VM memory and restart:\n\n```\ncrc stop\ncrc config set memory 14336\ncrc start\n```\n\nAfter CRC restarts, the pod should schedule automatically. If the pod is still pending after a few minutes, delete it to force a reschedule:\n\n```\noc delete pod -n $NAMESPACE -l app.kubernetes.io/component=main\n```\n\nIf your machine can’t spare 14 GB, you can also lower the pod’s memory request in `n8n-standalone-values.yaml`:\n\n```\nresources:\n main:\n requests:\n memory: 256Mi\n```\n\nThen upgrade: `helm upgrade n8n ~/n8n/ -n $NAMESPACE -f n8n-standalone-values.yaml`\n\n### DNS not resolving `.apps-crc.testing` or `api.crc.testing`\n\nOn Ubuntu, CRC configures DNS automatically. If it fails, restart NetworkManager:\n\n```\nsudo systemctl restart NetworkManager\n```\n\nIf still broken, add entries manually (CRC routes traffic through `127.0.0.1`):\n\n```\nsudo tee -a /etc/hosts <<EOF\n127.0.0.1 api.crc.testing\n127.0.0.1 console-openshift-console.apps-crc.testing\n127.0.0.1 oauth-openshift.apps-crc.testing\n127.0.0.1 default-route-openshift-image-registry.apps-crc.testing\nEOF\n```\n\nSubdomains\n\nWhen you expose Routes in the multi-instance section, new `*.apps-crc.testing` subdomains are created. Add them to `/etc/hosts` pointing to `127.0.0.1` if your browser can’t reach them.\n\n### n8n pod crashes with `EACCES: permission denied` writing to `/home/node/.n8n/`\n\nThis means the pod is running as a random OpenShift-assigned UID instead of UID 1000 (the `node` user the n8n image expects). It happens when `securityContext.enabled: false` is set in values without `runAsUser: 1000` and `fsGroup: 1000`, OpenShift assigns a random UID that can’t write to the PVC.\n\n**Fix:** Ensure `securityContext.enabled: true` is set in your values file, and that the chart has been patched to remove `seccompProfile` (see the SCC error section above). Both are required together.\n\n### View pod logs\n\n```\n# Main process\noc logs -n $NAMESPACE -l app.kubernetes.io/component=main --tail=50\n\n# Workers\noc logs -n $NAMESPACE -l app.kubernetes.io/component=worker --tail=50\n\n# Webhook processors\noc logs -n $NAMESPACE -l app.kubernetes.io/component=webhook-processor --tail=50\n```\n\n### All events in the namespace\n\n```\noc get events -n $NAMESPACE --sort-by='.lastTimestamp'\n```\n\n## Quick Reference\n\n### Re-export variables after reopening terminal\n\n```\neval $(crc oc-env)\nexport NAMESPACE=n8n-YYYYMMDD # use the date from your original deployment\noc login -u kubeadmin -p <password> https://api.crc.testing:6443\n```\n\n### Check cluster status\n\n```\ncrc status\n```\n\n### Open the OpenShift web console\n\n```\ncrc console\n```\n\nLog in with `kubeadmin` / your password to see a graphical view of everything running.\n\n### Things to save\n\n| Item | Why it matters |\n| ------------------------------- | --------------------------------------------- |\n| `kubeadmin` password | Log in to the cluster |\n| n8n encryption key | Lose this = all stored credentials unreadable |\n| `n8n-standalone-values.yaml` | Required for `helm upgrade` |\n| `n8n-multimain-ocp-values.yaml` | Required for `helm upgrade` |\n| MinIO root password | Access the MinIO console |\n| PostgreSQL password | Database access |\n\n## Next steps\n\n- Learn more about [configuring](../../../configuration/environment-variables/) and [scaling](../../../scaling/overview/) n8n.\n- Or explore using n8n: try the [Quickstarts](../../../../try-it-out/).\n",
18069
18069
  "excerpt": "# Hosting n8n on OpenShift Local (CRC) This guide walks you through deploying n8n on OpenShift Local (CRC), Red Hat's tool for running a local OpenShift cluster. It mirrors AWS/EKS deployment, but runs entirely on your local machine. It's designed for testing n8n in an OpenShift environment locally, without cloud costs. You will need a machine with significant resources available, given how many resources OpenShift itself consumes. ## OpenShift concepts vs standard Kubernetes OpenShift is bu...",
18070
18070
  "sections": [
18071
18071
  {
@@ -18500,7 +18500,7 @@
18500
18500
  "codeExamples": 80,
18501
18501
  "complexity": "advanced",
18502
18502
  "readingTime": "19 min",
18503
- "contentLength": 28781,
18503
+ "contentLength": 28783,
18504
18504
  "relatedPages": []
18505
18505
  },
18506
18506
  "searchIndex": {