--- url: 'https://guides.deplo.io/ruby/active-storage.md' description: >- Complete guide for configuring Active Storage with S3-compatible object storage on Deploio including Nine S3 buckets, custom hostnames, and signed URLs. --- # Active Storage on Deploio **Deploio doesn't give you a disk to store files permanently.** It's because real hard disk storage is difficult to scale horizontally. So the [12factor](https://12factor.net/backing-services) industry best practice has been for quite some time to use cloud storage, most famously Amazon S3. We call this "object storage". ::: info If you absolutely need a real persistent and backed-up disk, consider using a [Nine CloudVM](https://nine.ch/products/root-cloud-server/) or [bring your own server hardware](https://nine.ch/de/produkte/colocation/) instead. ::: ## Amazon and Others You can use Amazon S3 together with Deploio as you would on any other hoster. First you set up the bucket on the third-party service (e.g. [AWS S3](https://aws.amazon.com/s3/) or [Swiss Backup by Informaniak](https://docs.infomaniak.cloud/object_storage/s3/)). Then you follow the official [Rails Guides on S3 service configuration](https://guides.rubyonrails.org/active_storage_overview.html#s3-service-amazon-s3-and-s3-compatible-apis). ## S3 Service by Nine Let's assume that you want to have your storage located in Switzerland and controlled by Nine. Then you need to be aware of the [pricing](https://docs.nine.ch/docs/object-storage/manage-buckets-and-users#pricing) and we need to configure your bucket first. ### Bucket and User Nine has multiple [datacenter locations](https://docs.nine.ch/docs/managed-kubernetes/nke/nine-kubernetes-engine#locations). We're going to use the default for Deploio, which is `nine-es34`. So let's create an S3 bucket for Deploio: ```sh nctl create bucket --location=nine-es34 {BUCKET_NAME} ``` In order to access the created bucket, you must first create a **bucket user**. This user must be created in the same location as the bucket. You can do this by running the following: ```sh nctl create bucketuser --location=nine-es34 {BUCKETUSER_NAME} ``` Additionally, you need to grant the bucket user permission to access the bucket. ```sh nctl update bucket {BUCKET_NAME} \ --permissions reader={BUCKETUSER_NAME} \ --permissions writer={BUCKETUSER_NAME} ``` After configuring the bucket user, you can retrieve the access key and secret key: ```sh nctl get bucketuser {BUCKETUSER_NAME} --print-credentials ``` Then set the environment variables using the information you retrieved. If you worked with a datacenter location other than `nine-es34`, adjust the endpoint accordingly. ```sh nctl update app {APP_NAME} --env="\ S3_ACCESS_KEY={ACCESS_KEY};\ S3_SECRET_KEY={SECRET_KEY};\ S3_ENDPOINT=https://es34.objects.nineapis.ch;\ S3_BUCKET={BUCKET_NAME}" ``` ### CORS Active Storage supports uploading files directly from the client to the bucket. To make the direct uploads work, you need to [configure CORS](https://guides.rubyonrails.org/active_storage_overview.html#cross-origin-resource-sharing-cors-configuration) on the bucket. ```sh nctl update bucket {BUCKET_NAME} \ --cors origins={APP_HOST} \ --cors allowed-headers=Content-Type,Content-MD5,Content-Disposition \ --cors response-headers=Content-Type,Content-MD5,Content-Disposition,ETag \ --cors max-age=3600 ``` ## Configure Active Storage To use the bucket in your Rails application, you need to configure Active Storage. You can do this by configuring a new service in the `config/storage.yml` file: ```yaml title="config/storage.yml" deploio: service: S3 access_key_id: <%= ENV["S3_ACCESS_KEY"] %> secret_access_key: <%= ENV["S3_SECRET_KEY"] %> endpoint: <%= ENV["S3_ENDPOINT"] %> region: us-east-1 # fake; running in Switzerland, operated by Nine bucket: <%= ENV["S3_BUCKET"] %> ``` ::: info For S3, a `region` must be specified. Deploio uses the S3 default value of `us-east-1`, even though the servers are in Switzerland, operated by Nine. See the [FAQ](../user-guide/faq.md#why-do-i-have-to-set-the-s3-region-to-us-east-1) for details. ::: The underlying ActiveStorage service (`ActiveStorage::Service::S3Service`) uses the [AWS SDK for Ruby](https://github.com/aws/aws-sdk-ruby). Accordingly, we need to install the gem, before being able to use the new service: ```ruby title="Gemfile" gem "aws-sdk-s3" ``` To use the newly created Deploio service, set the [`config.active_storage.service`](https://api.rubyonrails.org/classes/ActiveStorage/Service.html) configuration in the production environment: ```ruby title="config/environments/production.rb" config.active_storage.service = :deploio ``` If you want to try it locally, you can also configure it in `development.rb` temporarily. Then you would test in the `rails console` that file upload and download works like this: ```rb blob = ActiveStorage::Blob.create_and_upload!( io: StringIO.new("dummy"), filename: "dummy.txt", content_type: "text/plain" ) puts blob.download # "dummy" puts blob.url # "{S3_BUCKET}.es34.objects.nineapis.ch/9etnjjbujcqk7vm8tqzvsj2q8cpj?response-content-disposition=attachment%3B%20filename%3D%22dummy.txt%22%3B%20filename%2A%3DUTF-8%27%27dummy.txt&response-content-type=text%2Fplain&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=qqMGtWnoxWK58YAdB6MjVDTB7kgxSRST%2F20251217%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20251217T154115Z&X-Amz-Expires=300&X-Amz-SignedHeaders=host&X-Amz-Signature=04565c440d7a0d32b4ddecd372d242ad8df391cd686a26a551ae0c9b9dbdf31c" ``` ### Public Access Notice that per default you will receive a signed URL because Rails assumes that S3 buckets are not publicly accessible. You can change this by creating a public Deploio S3 bucket ```sh nctl create bucket --location=nine-es34 {BUCKET_NAME} --public-read ``` and then [adding the `public: true` flag](https://guides.rubyonrails.org/active_storage_overview.html#public-access) to the Active Storage configuration. Your URLs will then be accessible like this (without the signature part): ```text {S3_BUCKET}.es34.objects.nineapis.ch/9etnjjbujcqk7vm8tqzvsj2q8cpj ``` ### Custom Bucket Hostnames For production apps you might want to hide the fact that assets are hosted on Nine S3. This often has the two practical reasons: * **Appearance**: all URLs should only point to your app, e.g. www.example.com and assets.example.com for brand and reputation reasons. * **Performance**: there should be a CDN in front of your assets but TLS should still be end-to-end. So you need to be in control of DNS to provide the Let's Encrypt challenge. Per default, Rails serves the assets only from the default bucket host, which is `{BUCKET_NAME}.es34.objects.nineapis.ch`. So we need to add a custom bucket hostname: ```sh nctl update bucket {BUCKET_NAME} --custom-hostnames={S3_BUCKET_HOST} nctl update app {APP_NAME} --env="S3_BUCKET_HOST={S3_BUCKET_HOST}" ``` Deploio needs to verify that you really own a domain name before it will accept HTTP traffic to your custom host on their side. So you need to add two DNS records at your DNS provider: * `CNAME` for your domain to `es34.objects.nineapis.ch` * `TXT` record for ownership verification The verification record can be retrieved via `nctl`: ```sh nctl get bucket {APP_NAME} --output="yaml" ``` The output will look something like that. Look out for the `txtRecordValue` ```yaml status: atProvider: customHostnamesVerification: cnameTarget: es34.objects.nineapis.ch statusEntries: - checkType: CAA latestSuccess: "2025-12-17T13:43:03Z" name: {S3_BUCKET_HOST} - checkType: CNAME latestSuccess: "2025-12-17T13:43:03Z" name: {S3_BUCKET_HOST} txtRecordValue: nine-bucket-verification=deploio-test-assets-renuotest-8432189 endpoint: es34.objects.nineapis.ch ``` Your assets should be reachable now under names like ```text https://assets.example.com/9etnjjbujcqk7vm8tqzvsj2q8cpj ``` but it's not clear yet how Active Storage can serve these URLs. If you're using [Proxy Mode](https://guides.rubyonrails.org/active_storage_overview.html#putting-a-cdn-in-front-of-active-storage) and **public** buckets only, then you can generate `cdn_image_url` helpers for your frontend and you're done. If you're using the default [Redirect Mode](https://guides.rubyonrails.org/active_storage_overview.html#redirect-mode) then you'd best follow along with the next section, which is simpler and even supports signed URLs for your custom host names. #### Signed URLs ::: info Underlying Deploio technology (Nutanix) doesn't support custom hostnames on its own. Therefore Deploio has a lightweight proxy in place relaying your custom host to `es34.objects.nineapis.ch`. For signed URLs to pass-through, we need to tell Active Storage to replace the host part of the generated and signed URL with your custom host. The proxy will pick it up and replace the custom host with the Deploio S3 host. The Nutanix S3 service can then verify the complete URL including signature. If you want to know more about how this works, have a look at the lightning talk ["Deploio S3"](https://docs.google.com/presentation/d/1o5LMgcUcVqqZlIQ5mCWJkD9CvYGFML6V7sQxMFkV6wg/edit?slide=id.g3b1e491c942_0_0#slide=id.g3b1e491c942_0_0). ::: To support signed URLs with custom hostnames, you currently need to register your own `ActiveStorage::Service` in `lib/active_storage/service/deploio_s3_service.rb`: ```ruby title="lib/active_storage/service/deploio_s3_service.rb" require "active_storage/service/s3_service" module ActiveStorage class Service class DeploioS3Service < ActiveStorage::Service::S3Service DEFAULT_REGION = "us-east-1" # fake; running in Switzerland, operated by Nine def initialize(host: nil, region: DEFAULT_REGION, **) @host = host super(region:, **) end def url(...) @host.blank? ? super : custom_host(super) end def url_for_direct_upload(...) @host.blank? ? super : custom_host(super) end private def custom_host(uri) uri = URI.parse(uri) uri.host = @host uri.to_s end end end end ``` Finally, change the config to use the new service: ```diff title="config/storage.yml" deploio: - service: S3 + service: DeploioS3 access_key_id: <%= ENV["S3_ACCESS_KEY"] %> secret_access_key: <%= ENV["S3_SECRET_KEY"] %> endpoint: <%= ENV["S3_ENDPOINT"] %> - region: us-east-1 # fake; running in Switzerland, operated by Nine bucket: <%= ENV["S3_BUCKET"] %> + host: <%= ENV["S3_BUCKET_HOST"] %> ``` ### Example App We also provide an example app that has Active Storage configured to work with Nine S3 buckets. See the [examples repository](https://github.com/ninech/deploio-examples/tree/main#ruby-on-rails-with-activestorage) for more details. ## Next Steps Do you need **background jobs** for your application? Proceed to the next step. --- --- url: 'https://guides.deplo.io/php/build-environment.md' description: >- Configuration guide for PHP build environment including web directory setup and web server selection (PHP built-in, Apache HTTPD, or NGINX). --- # Build Environment The build process offers a few environment variables to adjust it to your use case. See the [how to](https://paketo.io/docs/howto/php/) section of the documentation for all available variables. ## Configure the web directory To avoid exposing project files over the web, it is best practice to use a subfolder of your application as web root. A typical location for this is the directory `public`. Set `BP_PHP_WEB_DIR` to your web root directory: ```bash --build-env=BP_PHP_WEB_DIR=public ``` When the web server is Apache HTTPD or NGINX, the web directory defaults to `htdocs`. ## Selecting a Web Server By default, the PHP built-in web server will be used. For production use cases, we recommend using Apache HTTPD or NGINX: :::tabs key:webserver \== PHP Built-in Web Server ```bash --build-env=BP_PHP_SERVER=php-server ``` \== Apache HTTPD Web Server ```bash --build-env=BP_PHP_SERVER=httpd ``` \== NGINX Web Server ```bash --build-env=BP_PHP_SERVER=nginx ``` ::: Additionally, if required, the web server can be customized further by providing [your own server-specific config file](https://paketo.io/docs/howto/php/#provide-your-own-web-server-configuration-file). ## Next Steps In the next step, we will set up a Symfony project and then configure various storage options for it. --- --- url: 'https://guides.deplo.io/user-guide/ci-cd-integration.md' description: >- Instructions for automating deployments using nctl CLI in CI/CD pipelines with API service accounts, deployment triggers, and status feedback scripts. --- # CI/CD Integration This guide explains how you can setup a CI/CD pipeline to automate deployments. We'll provide examples for GitHub Actions and Semaphore. Furthermore, we explain how you could setup review apps. ## Prerequisites Before setting up CI/CD, you'll need: * An existing Deploio application linked to a Git repository * An API Service Account (ASA) for authentication (see [here](#create-an-api-service-account)) ## Continuous Integration ### Linters and tests The following workflow shows an example CI pipeline with GitHub Actions. It runs linting and tests in parallel. See [Continuous Deployment](#continuous-deployment) for details on how to setup the deployment step. ```yaml name: CI on: push: branches: [main, develop] pull_request: jobs: lint: runs-on: ubuntu-latest timeout-minutes: 5 steps: - uses: actions/checkout@v4 - name: Install dependencies run: npm ci - name: Run linters run: npm run lint test: runs-on: ubuntu-latest timeout-minutes: 10 steps: - uses: actions/checkout@v4 - name: Install dependencies run: npm ci - name: Run tests run: npm test ``` ### Review Apps Review apps are currently not supported yet in the Deploio cockpit. However, we provide you the commands that you can use to automate the setup within your CI/CD pipeline. This makes it fully customizable to your use case. The integration requires two local scripts. * `bin/deploy_review_app` to copy the template app and to point the new app to your feature branch * `bin/delete_review_app` to clean up the created review app and it's accessories (DB, Redis, etc.) These scripts interact with Deploio in the following way. ```mermaid sequenceDiagram actor Dev as Developer participant CI as CI / CLI participant Depl as Deploio Note over Dev, Depl: Deploy Dev->>CI: Open pull request CI->>Depl: Copy template app (if missing) CI->>Depl: Create accessories (DB, etc.) (if missing) CI->>Depl: Set review app git revision & ENV variables Depl-->>Dev: Review app URL Note over Dev, Depl: Cleanup (on PR close/merge) Dev->>CI: Close/merge PR CI->>Depl: Delete review app & accessories ``` We recommend that you consider the scripts as "templates". You can copy them to your project and customize them as you want. You might want to replace the Postgres commands with MySQL, or create additional Redis services for example. `bin/deploy_review_app` ```bash #!/usr/bin/env bash set -e BRANCH_NAME="${1:-$(git branch --show-current)}" case "$BRANCH_NAME" in main|master|develop) echo "Skipping deploy for branch $BRANCH_NAME"; exit 0 ;; esac UNIQUE_SUFFIX=$(echo -n "$BRANCH_NAME" | sha1sum | cut -c1-8) REVIEW_APP_NAME="review-app-${UNIQUE_SUFFIX}" echo "Deploying $REVIEW_APP_NAME for branch $BRANCH_NAME..." # Copy App if missing echo "Checking App..." nctl get app "$REVIEW_APP_NAME" -p "$DEPLOIO_PROJECT" >/dev/null 2>&1 || \ nctl copy app "$DEPLOIO_TEMPLATE_APP" -p "$DEPLOIO_PROJECT" --start --target-name="$REVIEW_APP_NAME" # Init Economy DB if missing echo "Checking Postgres DB..." nctl get postgresdatabase "$REVIEW_APP_NAME" -p "$DEPLOIO_PROJECT" >/dev/null 2>&1 || \ nctl create postgresdatabase "$REVIEW_APP_NAME" -p "$DEPLOIO_PROJECT" --location=nine-es34 --backup-schedule=disabled --wait DATABASE_URL=$(nctl get postgresdatabase "$REVIEW_APP_NAME" -p "$DEPLOIO_PROJECT" --print-connection-string) # Set git revision and ENVs echo "Updating App..." nctl update app "$REVIEW_APP_NAME" -p "$DEPLOIO_PROJECT" \ --git-revision="${BRANCH_NAME}" \ --env="DATABASE_URL=${DATABASE_URL}" \ --skip-repo-access-check \ $ENV_FLAGS # Output app URL APP_URL=$(nctl get app "$REVIEW_APP_NAME" -p "$DEPLOIO_PROJECT" -o json | jq -r '.status.atProvider.defaultURLs[0] // empty') echo "app-name=$REVIEW_APP_NAME" if [ -n "$APP_URL" ]; then echo "app-url=$APP_URL" fi # Wait for release to succeed echo "Waiting for release..." for i in $(seq 1 60); do STATUS=$(nctl get releases -a "$REVIEW_APP_NAME" -p "$DEPLOIO_PROJECT" -o json | jq -r '.[0].status.atProvider.releaseStatus // empty') case "$STATUS" in available|superseded) echo "release-status=success"; exit 0 ;; failed) echo "release-status=error"; exit 1 ;; esac sleep 5 done echo "release-status=error" exit 1 ``` `bin/delete_review_app` ```bash #!/usr/bin/env bash set -e BRANCH_NAME="${1:-$(git branch --show-current)}" case "$BRANCH_NAME" in main|master|develop) echo "Skipping delete for branch $BRANCH_NAME"; exit 0 ;; esac UNIQUE_SUFFIX=$(echo -n "$BRANCH_NAME" | sha1sum | cut -c1-8) REVIEW_APP_NAME="review-app-${UNIQUE_SUFFIX}" echo "Deleting $REVIEW_APP_NAME for branch $BRANCH_NAME..." nctl delete app "$REVIEW_APP_NAME" -p "$DEPLOIO_PROJECT" --force --wait || true nctl delete postgresdatabase "$REVIEW_APP_NAME" -p "$DEPLOIO_PROJECT" --force --wait || true echo "Deleted $REVIEW_APP_NAME" ``` ::: info You might be wondering why we force delete the resources here. This is in place to skip the deletion confirmation. The `--force` flag still respects the deletion protection mechanism on your main app. You could limit the risk by enabling deletion protection for your production environments. ::: #### GitHub Actions To automate the review app creation, you could setup e.g. a GitHub Actions workflow. The following workflow runs automatically as soon as you open a PR, mark it ready for review or close it. In addition, it can also be triggered manually in the Actions tab. Once the latest release of the review app is successful, it will display the deployment in your pull request. ```yaml name: Review App on: pull_request: types: [opened, ready_for_review, closed] workflow_dispatch: jobs: deploy: if: github.event.action != 'closed' && !github.event.pull_request.draft runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Install nctl run: | echo 'deb [trusted=yes] https://repo.nine.ch/deb/ /' | sudo tee /etc/apt/sources.list.d/repo.nine.ch.list sudo apt-get update -qqo Dir::Etc::sourcelist=/etc/apt/sources.list.d/repo.nine.ch.list sudo apt-get install -qq nctl - name: Authenticate nctl run: | nctl auth login \ --api-client-id=${{ secrets.NCTL_API_CLIENT_ID }} \ --api-client-secret=${{ secrets.NCTL_API_CLIENT_SECRET }} \ --organization=${{ secrets.NCTL_ORGANIZATION }} - name: Create deployment id: deployment env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | DEPLOYMENT_ID=$(gh api repos/${{ github.repository }}/deployments \ --input - --jq '.id' \ <<< '{"ref":"${{ github.head_ref || github.ref_name }}","environment":"review-app","auto_merge":false,"required_contexts":[]}') echo "id=$DEPLOYMENT_ID" >> "$GITHUB_OUTPUT" gh api repos/${{ github.repository }}/deployments/$DEPLOYMENT_ID/statuses \ -f state=pending \ -f description="Deploying review app..." - name: Deploy review app id: deploy env: DEPLOIO_PROJECT: my-project DEPLOIO_TEMPLATE_APP: main run: | OUTPUT=$(bin/deploy_review_app "${{ github.head_ref || github.ref_name }}") echo "$OUTPUT" echo "$OUTPUT" | grep "^app-url=" >> "$GITHUB_OUTPUT" || true echo "$OUTPUT" | grep "^app-name=" >> "$GITHUB_OUTPUT" || true - name: Deployment success if: success() env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | gh api repos/${{ github.repository }}/deployments/${{ steps.deployment.outputs.id }}/statuses \ -f state=success \ -f environment_url="${{ steps.deploy.outputs.app-url }}" \ -f description="Review app deployed" - name: Deployment error if: failure() && steps.deployment.outputs.id env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | gh api repos/${{ github.repository }}/deployments/${{ steps.deployment.outputs.id }}/statuses \ -f state=error \ -f description="Review app deployment failed" cleanup: if: github.event.action == 'closed' runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Install nctl run: | echo 'deb [trusted=yes] https://repo.nine.ch/deb/ /' | sudo tee /etc/apt/sources.list.d/repo.nine.ch.list sudo apt-get update -qqo Dir::Etc::sourcelist=/etc/apt/sources.list.d/repo.nine.ch.list sudo apt-get install -qq nctl - name: Authenticate nctl run: | nctl auth login \ --api-client-id=${{ secrets.NCTL_API_CLIENT_ID }} \ --api-client-secret=${{ secrets.NCTL_API_CLIENT_SECRET }} \ --organization=${{ secrets.NCTL_ORGANIZATION }} - name: Delete review app env: DEPLOIO_PROJECT: my-project run: bin/delete_review_app "${{ github.head_ref || github.ref_name }}" - name: Deactivate deployment env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | DEPLOYMENT_ID=$(gh api "repos/${{ github.repository }}/deployments?ref=${{ github.head_ref || github.ref_name }}&environment=review-app" \ --jq '.[0].id' 2>/dev/null || true) if [ -n "$DEPLOYMENT_ID" ] && [ "$DEPLOYMENT_ID" != "null" ]; then gh api repos/${{ github.repository }}/deployments/$DEPLOYMENT_ID/statuses \ -f state=inactive \ -f description="Review app deleted" fi ``` ::: info Replace `my-project` with your Deploio project name and `main` with the name of your template application. The template app is copied to create each review app, so it should be configured with your desired defaults. ::: ## Continuous Deployment ### Automate deployments When you link a GitHub repository and target branch to your Deploio application, the application automatically re-deploys whenever you push a change to that branch. If this is sufficient for your workflow, no additional CI/CD setup is needed. For more control — such as deploying only after tests pass, deploying specific commits, or getting deployment status feedback — you can automate deployments using `nctl` in your CI/CD pipeline. The following sections explain how to do this. ### Revision-based deployments The concept behind revision-based deployments is pretty simple. Instead of pointing your Deploio app to a branch, we point it to a specific git revision (commit SHA). This way, the Deploio build is triggered exactly for the specified state of the repository. #### Flow The following sequence diagram summarizes the revision-based deployment flow: ```mermaid sequenceDiagram participant Dev as Developer participant CI as CI/CD Pipeline participant Depl as Deploio Dev->>CI: Push code changes CI->>CI: optional: Run checks (tests, linters, etc.) CI->>Depl: Authenticate with nctl CI->>Depl: Update app to point to specific git revision Depl->>Depl: Trigger build and release CI->>Depl: Poll build and release status Depl-->>CI: Build and release status ``` #### Install `nctl` Configure your CI process to install and authenticate the `nctl` CLI. You'll need the following secrets set in your CI environment: | Secret | Description | |---|---| | `NCTL_API_CLIENT_ID` | The client ID from your API Service Account | | `NCTL_API_CLIENT_SECRET` | The client secret from your API Service Account | | `NCTL_ORGANIZATION` | Your Nine organization name | Install and authenticate `nctl`: ```bash # Install nctl (Debian/Ubuntu) echo 'deb [trusted=yes] https://repo.nine.ch/deb/ /' | sudo tee /etc/apt/sources.list.d/repo.nine.ch.list sudo apt-get update -qqo Dir::Etc::sourcelist=/etc/apt/sources.list.d/repo.nine.ch.list sudo apt-get install -qq nctl ``` #### Create an API Service Account Create an API Service Account (ASA) so your CI pipeline can authenticate without using personal credentials. Create a new ASA: ```bash nctl create asa {token_name} ``` View the token: ```bash nctl get apiserviceaccount {token_name} --print-token ``` Authenticate `nctl` using the ASA credentials: ```bash nctl auth login \ --api-client-id=$NCTL_API_CLIENT_ID \ --api-client-secret=$NCTL_API_CLIENT_SECRET \ --organization=$NCTL_ORGANIZATION ``` ⚠️ Store the client ID and secret as secrets in your CI environment. Never commit them to your repository. #### Update app git revision Set the following environment variables in your CI pipeline: | Variable | Description | |---|---| | `DEPLOIO_PROJECT` | Your Deploio project name | | `DEPLOIO_APP_NAME` | Your Deploio application name | Then use `nctl` to update the application to a specific git revision: ```bash nctl update app $DEPLOIO_APP_NAME \ --project $DEPLOIO_PROJECT \ --git-revision=$(git rev-parse HEAD) \ --skip-repo-access-check ``` #### Poll build and release status After triggering a deployment, you can poll Deploio for the build and release status. This lets your CI pipeline report whether the deployment succeeded or failed. Below is an example script in Ruby that checks the build and release status. You can adapt this to any language. ```ruby require 'yaml' require 'open3' TIMEOUT_IN_SECONDS = 300 INTERVAL_IN_SECONDS = 30 PROJECT = ENV['DEPLOIO_PROJECT'] APP_NAME = ENV['DEPLOIO_APP_NAME'] REVISION = `git rev-parse HEAD`.strip def fetch_builds(project, app_name) command = "nctl get builds --project=#{project} --application-name=#{app_name} --output=yaml" stdout, stderr, status = Open3.capture3(command) unless status.success? puts "Error fetching build information: #{stderr}" exit 1 end YAML.load_stream(stdout) end def fetch_releases(project, app_name) command = "nctl get releases --project=#{project} --application-name=#{app_name} --output=yaml" stdout, stderr, status = Open3.capture3(command) unless status.success? puts "Error fetching release information: #{stderr}" exit 1 end YAML.load_stream(stdout) end def find_build_for_revision(builds, revision) builds.find do |build| build.dig('spec', 'forProvider', 'sourceConfig', 'git', 'revision') == revision end end def find_release_for_build(releases, build_name) releases.find do |release| release.dig('spec', 'forProvider', 'build', 'name') == build_name end end def build_status(build) build.dig('status', 'atProvider', 'buildStatus') end def release_status(release) release.dig('status', 'atProvider', 'releaseStatus') end puts "(1/2) Checking build status for revision #{REVISION}..." elapsed = 0 build = nil while elapsed < TIMEOUT_IN_SECONDS builds = fetch_builds(PROJECT, APP_NAME) build = find_build_for_revision(builds, REVISION) if build case build_status(build) when 'success' puts "Build succeeded for revision #{REVISION}" break when 'failed' puts "Build failed for revision #{REVISION}" exit 1 else puts "Build status is #{build_status(build)}, waiting..." end else puts "No matching build found for revision #{REVISION}, waiting..." end sleep INTERVAL_IN_SECONDS elapsed += INTERVAL_IN_SECONDS end if elapsed >= TIMEOUT_IN_SECONDS || build.nil? puts "Build check timed out after #{TIMEOUT_IN_SECONDS} seconds." exit 1 end build_name = build.dig('metadata', 'name') puts "(2/2) Checking release status for build #{build_name}..." elapsed = 0 while elapsed < TIMEOUT_IN_SECONDS releases = fetch_releases(PROJECT, APP_NAME) release = find_release_for_build(releases, build_name) if release case release_status(release) when 'available' puts "Release is available for build #{build_name}. Deployment successful." exit 0 when 'failed' puts "Release failed for build #{build_name}." exit 1 else puts "Release status is #{release_status(release)}, waiting..." end else puts "No matching release found for build #{build_name}, waiting..." end sleep INTERVAL_IN_SECONDS elapsed += INTERVAL_IN_SECONDS end puts "Release check timed out after #{TIMEOUT_IN_SECONDS} seconds." exit 1 ``` Run the script after triggering the deployment: ```bash ruby bin/check_deploio_deployment_status.rb ``` ### GitHub Actions Here's an example GitHub Actions workflow that deploys your application after tests pass: ```yaml name: Deploy on: push: branches: [main] jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Run tests run: | # Add your test commands here echo "Running tests..." deploy: needs: test runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Install nctl run: | echo 'deb [trusted=yes] https://repo.nine.ch/deb/ /' | sudo tee /etc/apt/sources.list.d/repo.nine.ch.list sudo apt-get update -qqo Dir::Etc::sourcelist=/etc/apt/sources.list.d/repo.nine.ch.list sudo apt-get install -qq nctl - name: Authenticate nctl run: | nctl auth login \ --api-client-id=${{ secrets.NCTL_API_CLIENT_ID }} \ --api-client-secret=${{ secrets.NCTL_API_CLIENT_SECRET }} \ --organization=${{ secrets.NCTL_ORGANIZATION }} - name: Deploy to Deploio run: | nctl update app ${{ vars.DEPLOIO_APP_NAME }} \ --project ${{ vars.DEPLOIO_PROJECT }} \ --git-revision=$(git rev-parse HEAD) \ --skip-repo-access-check ``` ### Semaphore Create a deployment pipeline file (e.g., `main-deploy.yml`) that installs `nctl`, authenticates, and triggers the deployment: ```yaml version: v1.0 name: Deploy to Deploio agent: machine: type: f1-standard-4 os_image: ubuntu2204 blocks: - name: deploy task: secrets: - name: deploio-credentials jobs: - name: deploy commands: - echo 'deb [trusted=yes] https://repo.nine.ch/deb/ /' | sudo tee /etc/apt/sources.list.d/repo.nine.ch.list - sudo apt-get update -qqo Dir::Etc::sourcelist=/etc/apt/sources.list.d/repo.nine.ch.list - sudo apt-get install -qq nctl - nctl auth login --api-client-id=$NCTL_API_CLIENT_ID --api-client-secret=$NCTL_API_CLIENT_SECRET --organization=$NCTL_ORGANIZATION - nctl update app $DEPLOIO_APP_NAME --project $DEPLOIO_PROJECT --git-revision=$(git rev-parse HEAD) --skip-repo-access-check ``` #### Auto-promote after tests In your main pipeline file, add a promotion that triggers the deployment pipeline when tests pass: ```yaml promotions: - name: deploy deployment_target: production pipeline_file: main-deploy.yml auto_promote: when: result = 'passed' and branch = 'main' ``` --- --- url: 'https://guides.deplo.io/user-guide/claude-plugin.md' description: >- Deploy and manage Deploio apps using plain English in Claude Code. No CLI commands to memorise. --- # Claude Code Plugin The **deploio-claude-plugin** adds Deploio skills to [Claude Code](https://claude.ai/code). Instead of looking up `nctl` commands, you describe what you want: ``` Deploy my Rails app to Deploio My app is throwing 503s, what's wrong? Add a PostgreSQL database and wire it up Set up GitHub Actions to deploy on push ``` Claude picks the right skill, explains what it will do, and runs `nctl` on your behalf. Destructive operations always require explicit confirmation. ::: info Community tool Created and maintained by [Renuo](https://renuo.ch). Nine maintains a fork on [Github](https://github.com/ninech/deploio-skills). ::: ## Prerequisites 1. **Claude Code** installed ([get it here](https://claude.ai/code)) 2. **`nctl` v1.16.0+** installed: MacOS installation ```bash brew install ninech/tap/nctl ``` Linux binary can be downloaded from: https://github.com/ninech/nctl/releases/latest 3. `nctl` is properly authenticated ```bash nctl auth login # opens browser OAuth nctl auth whoami # verify access ``` ## Installation Run this from your project directory (or anywhere for a global install): ```bash /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/ninech/deploio-skills/refs/heads/main/install.sh)" ``` The installer asks whether to install **globally** (`~/.claude/`) or **per-project** (`./.claude/`). For non-interactive use: ```bash DEPLOIO_INSTALL_SCOPE=global /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/ninech/deploio-skills/refs/heads/main/install.sh)" ``` or ```bash DEPLOIO_INSTALL_SCOPE=project /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/ninech/deploio-skills/refs/heads/main/install.sh)" ``` **To update:** re-run the same install command. It overwrites with the latest version. **To uninstall:** ```bash /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/renuo/deploio-claude-plugin/main/uninstall.sh)" ``` ## Skills Five skills are installed. Claude selects the right one based on what you ask. | Skill | What it covers | |-----------------------|---------------------------------------------------------------| | **deploio-deploy** | First-time deployment from a git repo to a live HTTPS URL | | **deploio-manage** | Day-to-day operations on running apps | | **deploio-debug** | Diagnosing and fixing crashes, failed deployments, and errors | | **deploio-provision** | Provisioning databases, Redis, and object storage | | **deploio-ci-cd** | Setting up automated deployment pipelines | ### First deploy: `deploio-deploy` Detects your framework, sets sensible defaults, and shows you a plan before touching anything. Supported frameworks: **Rails, Node.js, Django, Flask/FastAPI, PHP/Laravel, Go, Docker** ``` Deploy my Rails app to Deploio Host my Next.js app on Deploio ``` ### Day-to-day management: `deploio-manage` Handles everything on a running app. Picks up your app name and project from the git remote so you don't have to specify them. ``` Scale my app to 3 replicas Add DATABASE_URL env var Tail the logs Open a Rails console Roll back to the last working version Add a Sidekiq worker Set up a custom domain Restart the app ``` ### Debugging: `deploio-debug` Fetches build logs, release history, and runtime stats in parallel, then tells you what went wrong and offers to fix it. ``` My app crashed after the latest deploy Getting 503 bad gateway errors Build is failing, what's wrong? App is using too much memory ``` ### Backing services: `deploio-provision` Creates the service, extracts credentials, and sets the right environment variables on your app. | Service | Injected env var(s) | |---------------------------------|----------------------------------------------------------------------------------------| | PostgreSQL (Economy / Business) | `DATABASE_URL` | | MySQL (Economy / Business) | `DATABASE_URL` | | Redis-compatible KVS | `REDIS_URL` | | OpenSearch | `OPENSEARCH_URL` | | S3-compatible Object Storage | `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `AWS_REGION`, `S3_BUCKET`, `S3_ENDPOINT` | ``` Add a PostgreSQL database and wire it up I need Redis for Sidekiq Set up S3-compatible object storage ``` ### CI/CD pipeline: `deploio-ci-cd` Creates a Deploio service account, writes the workflow file, and walks you through adding the required secrets to your CI platform. Supported platforms: **GitHub Actions, GitLab CI, CircleCI, Bitbucket Pipelines**, and any Debian/Ubuntu-based CI system. Available patterns: * **Single environment:** push to `main` to deploy * **Multi-environment:** `develop` to staging, `main` to production * **Per-PR preview environments:** app created on PR open, deleted on PR close ``` Set up GitHub Actions to auto-deploy on push to main Add a staging environment Create per-PR preview apps on Deploio ``` ## Slash commands Two shortcuts are installed alongside the skills: | Command | Effect | |-----------|------------------------------------| | `/deploy` | Triggers the deploy skill directly | | `/debug` | Triggers the debug skill directly | ## Safety * **Destructive operations require confirmation:** deleting apps, databases, or storage; pausing an app; running `db:drop` or `db:reset` all prompt you before proceeding. * **Plan before action:** every skill describes what it will do before running any `nctl` command. * **Least privilege:** the CI/CD service account is project-scoped with minimal permissions. --- --- url: 'https://guides.deplo.io/user-guide/code-repository-setup.md' description: >- Instructions for connecting Git repositories to Deploio using SSH keys or HTTPS for GitHub, GitLab, Bitbucket, and private Git servers. --- # Code Repository Setup To deploy your application with Deploio, you must connect your code repository so that we can fetch your application code during the build process. We explain how to set it up in this section. We support all major Git platforms, including GitHub, GitLab, Bitbucket, and private Git servers. This guide explains how to set up secure access and configure your repository properly. ### GitHub [//]: # "TODO: speak to Nine about OAuth support - I would expect a button to authorize with GitHub" When creating a new application in the Cockpit or via the nctl CLI, you will need to enter the **Git URL** and authentication details. Deploio supports both **HTTPS** and **SSH** access methods for GitHub repositories. ##### HTTPS Access with Personal Access Token (PAT) 1. [Generate a GitHub Personal Access Token](https://github.com/settings/tokens) with `repo` scope (or fine-grained read-only access). 2. In Cockpit: * Set the **Git URL** to your repo, e.g. ``` https://github.com/your-org/your-repo.git ``` * Enter the **Username**: your GitHub username * Enter the **Password**: your GitHub PAT > ⚠️ Your PAT acts like a password — do not share or expose it. ##### SSH Key Integration 1. **Generate an SSH key** (if you don’t have one yet): ```bash ssh-keygen -t ed25519 -C "deploio-access" ``` Save it somewhere like `~/.ssh/deploio_id_ed25519`. Alternatively, you can use a tool like 1Password to generate and store the key securely. 2. **Add the public key to GitHub** * Manually via GitHub: Go to your repository → **Settings > Deploy Keys** → **Add deploy key**, give it a name, and paste the **public key**. Only read access is required. * Or via the CLI: ```bash gh repo deploy-key add \ --repo your-org/your-repo \ --title deploio_deploy_key_main \ < ~/.ssh/deploio_id_ed25519.pub ``` 3. **Provide the private key to Deploio** when creating the app in Cockpit or via `nctl`: This can be done via the `--git-ssh-private-key` flag or the `--git-ssh-private-key-from-file` flag to specify the SSH key to use: ```bash nctl create app main \ --project my-project \ --git-ssh-private-key-from-file=~/.ssh/deploio_id_ed25519 ``` > ⚠️ Ensure the key is unquoted — quotation marks around the private key must be removed before use. ### GitLab Deploio works with both GitLab.com and self-hosted GitLab instances. #### SSH Key Integration Follow the same steps as GitHub: generate a key pair. To add the public key in GitLab, follow [this guide](https://docs.gitlab.com/user/project/deploy_keys/). Then provide the private key when creating the app in Cockpit or via `nctl`, as in the GitHub example. ### Bitbucket Deploio works with Bitbucket Cloud. #### SSH Key Integration Generate a key pair using the same steps as GitHub. To add the deploy key, follow [Bitbucket's SSH access docs](https://support.atlassian.com/bitbucket-cloud/docs/configure-ssh-and-two-step-verification/). Then provide the private key when creating the app in Cockpit or via `nctl`, as in the GitHub example. ### Private git server If you're using a custom Git server (e.g., Gitea, Gitolite, bare Git over SSH): 1. Ensure the server is accessible from Deploio's build environment (no firewall blocks). 2. Add a **deploy key** (the SSH public key) to your Git server. The method will depend on the server type. 3. Provide the **private key** to Deploio just like with GitHub/GitLab. 4. Use the full SSH path for the repository: ```bash git@yourserver.com:org/repo.git ``` ## Repository Access Once you have successfully connected your git repository, Deploio starts polling every minute for new changes, unless your git revision points to a specific commit hash. In that case, Deploio will not poll at all until you update the hash via CLI or Cockpit. #### 🔐 Private Repositories * Require an SSH key to authenticate. * Best practice: create a **read-only deploy key per application**. * Periodically rotate keys for security. * Ensure your application has **access to the correct branch or tag**. #### 🌍 Public Repositories * No authentication needed. * Simply provide the HTTPS or SSH URL. * Still recommended to **pin a specific branch or tag** to ensure stability. --- --- url: 'https://guides.deplo.io/ruby/continuous-deployment.md' description: >- Guide for setting up continuous deployment pipelines for Rails applications using API service accounts, nctl CLI automation, and deployment status monitoring. --- # Configure Continuous Deployment for Your Rails Application There are two ways to automatically deploy your Rails application on Deploio: 1. **Polling** — Deploio polls your repository for changes (every minute) and deploys automatically. 2. **CI/CD pipeline** — Your CI pipeline tells Deploio to deploy a specific commit after tests pass. ## Option 1: Polling This is the simplest approach. Point your application at a branch, and Deploio will regularly check for new commits and redeploy when it detects changes: ```bash nctl update app {APP_NAME} --git-revision=main ``` No CI/CD setup is required. This is a good option for staging environments or projects that don't need a CI pipeline. It might also be an acceptable option if you work with dedicated release branches where you don't run your tests again. ::: warning With polling, Deploio might deploy every push to the git branch. This would start the deployment process immediately, before your tests have passed. Consider the next option, if you want to delay the deployment until your checks pass. ::: ## Option 2: CI/CD Pipeline With this approach, your CI pipeline can run checks first and then trigger a deployment by updating the application's git revision to a specific commit SHA. This gives you full control over what gets deployed. ### Prerequisites * A Rails application under version control with a remote repository on GitHub, GitLab, Bitbucket, or any other [Git hosting service](/user-guide/code-repository-setup.md) * A running Deploio Rails application. If you haven't deployed yet, follow the [Quick Start guide](quick-start.md). * A CI/CD tool like GitHub Actions, GitLab CI/CD, or CircleCI ### Create a Service Account ::: tip Before you create resources, ensure that the project you want to create the resources in is selected by running `nctl auth set-project {project_name}`. Alternatively, you can specify the project in every command using the `--project` flag. ::: To avoid storing your personal credentials in your CI/CD pipeline, create an API service account (ASA) that only has permissions within a project: ```bash nctl create apiserviceaccount {ASA_NAME} ``` Retrieve the token: ```bash nctl get apiserviceaccounts {ASA_NAME} --print-token ``` ### Configure CI/CD Environment Variables Set the following environment variables in your CI/CD tool: * `DEPLOIO_APP_NAME`: The name of your application in Deploio. * `DEPLOIO_PROJECT`: The name of the project in Deploio. * `NCTL_API_TOKEN`: The API token from the service account above. * `NCTL_ORGANIZATION`: Your organization name in Deploio. `NCTL_API_TOKEN` and `NCTL_ORGANIZATION` are used to authenticate the `nctl` CLI. Since the API token is sensitive, **store it as a secret** in your CI/CD tool. ### Deploy Script The following script can be used in any CI/CD tool that runs on Debian/Ubuntu: ```bash echo "deb [trusted=yes] https://repo.nine.ch/deb/ /" | sudo tee /etc/apt/sources.list.d/repo.nine.ch.list sudo apt-get update && sudo apt-get install nctl nctl auth login nctl update app $DEPLOIO_APP_NAME \ --project $DEPLOIO_PROJECT \ --git-revision=$(git rev-parse HEAD) \ --skip-repo-access-check ``` The script installs the `nctl` CLI, authenticates using the API token, and updates the git revision to the current commit. This tells Deploio to fetch and build that exact commit. If you are using a different operating system, adjust the installation step accordingly. See the [nctl setup instructions](https://github.com/ninech/nctl?tab=readme-ov-file#setup). ::: warning This example deploys the current commit. In a production environment, you may want to restrict deployments to a specific branch or tag. ::: ### Caveats The deploy script above is minimal and has some limitations: * It does not check if the deployment was successful — CD might fail silently. * It terminates immediately after updating the git revision, before the deploy finishes. ::: info A blocking mode for `nctl update app` is on the roadmap. Once available, the command can wait until the deployment finishes and exit with a non-zero status on failure, removing the need for a separate status check. ::: In the meantime, for a more robust setup that waits for the deployment to finish and checks its status, see the [deployment feedback guide](/user-guide/ci-cd-integration.md#poll-build-and-release-status), which includes an example status check script in Ruby. ### Troubleshooting If `nctl auth login` runs indefinitely, the `NCTL_API_TOKEN` is most likely not set correctly. Ensure that the token is available to the script and that the service account was created within the correct project. ## Next Steps Now that your application is live and deploying automatically, you'll want to keep an eye on it. Head over to the [Monitoring and Logs](/user-guide/monitoring-and-logs.md) guide to learn how to observe your application's logs and metrics. --- --- url: 'https://guides.deplo.io/php/continuous-deployment.md' description: >- Guide for setting up continuous deployment pipelines for PHP applications using API service accounts, nctl CLI automation, and deployment status monitoring. --- # Configure the CD for Your PHP Application ::: info Modern application workflows typically involve some sort of continuous integration and continuous deployment (CI/CD) process. This guide will help you set up a continuous deployment pipeline for your PHP application, independent of the CI/CD tool you choose. ::: ::: tip Preliminary Information If you do not intend to have a CI pipeline and still want to have your application deployed automatically, you can specify a branch to pull from using the `nctl` api (`nctl update application {application_name} --git-revision=my-branch`). Deploio will regularly check for changes in the specified branch and deploy the application if changes are detected. ::: ## Prerequisites Before you begin, you need to have the following: * A PHP application under version control with Git and a remote repository on GitHub, GitLab, Bitbucket, or any other [Git hosting service](/user-guide/code-repository-setup.md) * A running Deploio PHP application. If you haven't deployed your PHP application yet, follow the [Create a PHP Application](quick-start.md) guide. * A CI/CD tool like GitHub Actions, GitLab CI/CD, or CircleCI that is able to run bash scripts. Ideally, a CI pipeline already exists that executes your tests so that you can make sure your application is correct before deploying it. ## Create a Service Account ::: tip Before you create resources, ensure that the project you want to create the resources in is selected by running `nctl auth set-project {project_name}`. Alternatively, you can specify the project in every command using the `--project` flag. ::: To avoid having to store your personal credentials in your CI/CD pipeline, you should create an API service account (ASA) that only has permissions within a project. You can create a new service account using the `nctl` CLI: ```bash nctl create apiserviceaccount {asa_name} ``` After the service account is created, you will be able to query the service account's credentials using the following command: ```bash nctl get apiserviceaccounts {asa_name} --print-token ``` ## Configure the CD Pipeline Since the CD pipeline is highly dependent on the platform you are using, we will provide a general example of how you can configure the CD pipeline. ### Prerequisites To be able to run the deploy script, the following environment variables need to be set: * `DEPLOIO_APP_NAME`: The name of the PHP application in Deploio. * `DEPLOIO_PROJECT`: The name of the project in Deploio. * `NCTL_API_TOKEN`: The API token of the service account you created in the previous step. * `NCTL_ORGANIZATION`: The organization name in Deploio. The latter two environment variables are used to authenticate the `nctl` CLI. Since the API token is sensitive, it is recommended to **store it as a secret** in your CI/CD tool. ### Deploy Script You need to install the `nctl` command line tool into your CI/CD tool. The following script can be used in any CI/CD tool that is based on Debian/Ubuntu: ```bash echo "deb [trusted=yes] https://repo.nine.ch/deb/ /" | sudo tee /etc/apt/sources.list.d/repo.nine.ch.list sudo apt-get update && sudo apt-get install nctl nctl auth login nctl update app $DEPLOIO_APP_NAME \ --project $DEPLOIO_PROJECT \ --git-revision=$(git rev-parse HEAD) \ --skip-repo-access-check ``` The first step in the script adds the `nine.ch` Debian repository to the system, and the second step installs the `nctl` CLI. In case you are using a different operating system, you need to adjust the installation command accordingly. You can find instructions on how to install the `nctl` CLI in the [installation documentation](/user-guide/getting-started.md#installing-nctl). In the third step, the script authenticates the `nctl` CLI using the API token. Finally, the script updates the git-revision of the application and thus tells Deploio to fetch the latest version of your application from your specified git repository. ::: warning In this example, you are using the git revision of the current commit to deploy the application. This works in most cases, but you might want to adjust this to your needs. For example, in a production environment, you might want to ensure that the deployment can only be updated from a specific branch or tag. ::: ### Caveats The script provided above is a rather basic example of how you can deploy your PHP application and thus has some flaws: * It does not check if the deployment was successful and thus CD might fail silently. * It immediately terminates after the git revision was updated. This might be a problem if you want to run additional commands after the deployment was successful. [//]: # "TODO: There are plans to add the functionality into `nctl` to block the update command until the deployment is finished." To circumvent these issues, you might want to add a check that waits for the deployment to finish and then check its status. A more sophisticated approach including an example of a status check script in Ruby can be found [here](/user-guide/ci-cd-integration.md#poll-build-and-release-status). This Ruby script can be adapted for your preferred language and setup. ### Troubleshooting If you encounter issues when running the `nctl auth login` command such as it running indefinitely, most likely the `NCTL_API_TOKEN` is not set correctly. Ensure that the token is set correctly and that it is available to the script. Also, double check that the service account was created within the correct project and that the project is set correctly in the `DEPLOIO_PROJECT` environment variable. --- --- url: 'https://guides.deplo.io/user-guide/configuring-your-application.md' description: >- Complete reference for configuring applications on Deploio including environment variables, deploio.yaml, Procfile, worker jobs, deploy jobs, and resource sizing. --- # Configuring Your Application Your application isn't just about the code — it's also about how it runs. This section covers the essential configurations that define its behaviour, from environment variables and deployment files, to worker processes and background jobs. Here, you'll learn how to set up and fine-tune your app's internal mechanics to ensure smooth operation. ## Configuration Methods Deploio provides multiple ways to configure your application: ### 1. nctl (CLI) Using the `nctl` CLI tool, you can configure your application through commands. This is ideal for automation and scripting, for example retrieving environment variables from your current platform, and applying them at application creation. ```bash # Example: Creating an app with configuration nctl create app my-app --project my-project \ --env=DATABASE_URL:"postgres://user:password@host/db" \ --build-env=NODE_ENV:"production" \ --port=3000 \ --basic-auth ``` ::: info `app` is short for `application`. `nctl` also works if you use the long name `nctl create application my-app ...`. ::: ### 2. Cockpit (GUI) The Deploio Cockpit provides a user-friendly interface for configuring your application. Once the application is created, you can go to the Application page, and use the tabs, and the edit page to configure the application. The following tabs are available for configuration: #### Application Tabs | Tab | Description | |----------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Git** | Configure the git repository URL and authentication details for your application | | **Hosts** | Manage deployment hosts and view DNS configuration records (TXT and CNAME) for your domain registrar | | **Configuration** | Manage environment variables, build variables, and basic application settings (auth, port, replicas, size). Shows the source of each setting (default or `.deploio.yaml`) | | **Static Egress** | Configure static IP addresses for outbound traffic.[Learn more about static egress](https://docs.nine.ch/docs/managed-kubernetes/nke/static-egress-nke/) | | **Jobs** | View worker and scheduled jobs. For configuration, use [CLI or deploio.yaml](#worker-jobs) | | **Dockerfile Build** | View build options for Dockerfile-based applications. Configure using `--dockerfile-path` and `--dockerfile-build-context` flags. [Learn more about Dockerfile builds](https://docs.nine.ch/docs/deplo-io/dockerfile-build/) | | **Logs** | Access real-time application logs | | **Metrics** | Access app container metrics (memory & CPU usage) | | **Builds** | Monitor build status and history | | **Releases** | Track application releases and their status | #### Edit page You can also use the `edit` button on the top right of the page to edit the application. ![Edit button demonstration](/img/edit_button.gif) Here you can **add** a deploy job, worker jobs, scheduled jobs, as well as the basic configuration for your application (port, replicas, size, basic auth, etc). ### 3. `.deploio.yaml` A Git-tracked configuration file that can be stored alongside your application code. It will be read by the build system when building the application. This allows you to have all the configuration in one YAML file, and not have to use the CLI or Cockpit to configure your application. The `.deploio.yaml` file specifies the default values. If you overwrite a setting in the admin GUI or command line, they take precedence over the defaults from the file. You can use this file to: * [Define default environment variables](#environment-variables) * [Enable basic authentication](#basic-authentication) * [Set application configuration (e.g. size, port, replicas)](#web-application-configuration) * [Set up a deploy job](#deploy-job) * [Define background jobs (workers)](#worker-jobs) * [Define scheduled jobs (cron jobs)](#scheduled-jobs) Below is an example of a `.deploio.yaml` file. You can see an up-to-date list of fields that can be used in the [API docs](https://docs.nine.ch/api/#tag/ProjectConfig/operation/createAppsNineChV1alpha1NamespacedProjectConfig). ```yaml # Application size (micro, mini, standard-1, standard-2, standard-4) size: micro # Port the app is listening on. port: 8080 ## Sets the amount of replicas of the running app. replicas: 1 # Env variables which are passed to the app at runtime. env: - name: RESPONSE_TEXT value: "Hello from a Deploio app!" # enables basic authentication for the application - recommended to protect applications that are not yet productive enableBasicAuth: true # A job that runs before a new release gets deployed. deployJob: name: "hello" command: echo "Hello from a Deploio app! # A job that runs in the background non-stop. workerJobs: - name: "sidekiq-worker" command: "bundle exec sidekiq -e production -C config/sidekiq.yml" # A job that is set to run at specific times. scheduledJobs: - name: "daily-backup" schedule: "0 3 * * *" command: /app/backup.sh ``` ### 4. Procfile ::: warning Procfile Limitations Deploio only supports the `web` process type in Procfile. The `worker` and `release` process types are not supported. We strongly recommend using `.deploio.yaml` instead, which provides full support for all process types including: * Web processes * Worker jobs * Deploy jobs * Scheduled jobs For local development, you can use `Procfile.dev` to maintain your development environment configuration. ::: A Procfile is a simple text file that specifies the commands that should be executed to start your application. Each line in the Procfile follows the format: ``` : ``` #### Process Types * `web`: The main web process that handles HTTP requests. This is the only process type supported in Procfile. * `worker`: Not supported in Procfile. Use `.deploio.yaml` to configure worker jobs instead. * `release`: Not supported in Procfile. Use `.deploio.yaml` to configure deploy jobs instead. #### Example ``` web: bundle exec puma -C config/puma.rb ``` A number of configuration options use the cron syntax. You can see more information about the syntax [here](https://crontab.guru/). ### 5. project.toml Deploio supports the [`project.toml`](https://buildpacks.io/docs/for-app-developers/how-to/build-inputs/use-project-toml/) file to configure buildpacks (both the *Paketo* and *Heroku* ones). This file is part of the Cloud Native Buildpacks specification and allows you to control which files are included or excluded during the build process. This is useful when your repository contains files that would cause Deploio to auto-detect an unwanted buildpack. For example, if Node.js is only used for development purposes (linting, formatting) but not in production, you can exclude `package.json` and `package-lock.json` to prevent Deploio from adding the Node.js buildpack: ```toml [_] schema-version = "0.2" [io.buildpacks] exclude = [ "/package-lock.json", "/package.json", ] ``` See the [Cloud Native Buildpacks documentation](https://buildpacks.io/docs/for-app-developers/how-to/build-inputs/use-project-toml/) for the full list of available options. ## Configuration Topics ### Process Failure Handling Deploio automatically handles process failures for both web and worker processes: * If a process crashes or becomes unreachable on its specified port, Deploio will automatically attempt to restart it * A back-off strategy is implemented, which increases the time between restart attempts until it eventually gives up * This applies to both web and worker processes ### Environment Variables Environment variables allow you to customize your application's behavior between environments (e.g. development, staging, production) without changing code. When you connect on-demand services (like databases or key-value stores) to your application, Deploio automatically injects their connection details as runtime environment variables. These variables use a predictable prefix based on your chosen service type and reference name (e.g., `NINE_PG_DB_DSN`). ::: info Injected service variables only become available when a new release is created. If your application is already running, you will need to trigger a redeployment (e.g., via `nctl update app {APP_NAME} --retry-release`) for the changes to take effect. ::: #### Build Variables Build variables are available **only during the build phase** (i.e., when the container is being created using the Dockerfile or buildpack). They are not available at runtime. These are useful for tools like Webpack, Babel, or asset precompilation that may require certain environment variables to be set during the build process. #### Runtime Variables Runtime variables are loaded **every time your application boots up**, making them suitable for configuring behavior, authentication, credentials, and other per-environment or per-deploy settings. These are useful for setting up database connection strings, API keys, and other sensitive information that should not be hard-coded into your application. #### Configuring Environment Variables :::tabs key:config \== nctl Environment variables can be configured using the `nctl` CLI tool. In particular, you can use the `--build-env` and `--env` flags to set build and runtime variables, respectively, in the format `--env=KEY=VALUE;...`. Environment variables can be set up during app creation, or when updating the app. For a brand-new application: ```bash # Build variables (only during build phase) nctl create app my-app --build-env=NODE_ENV:"production";SENTRY_AUTH_TOKEN:"xyz123" # Runtime variables (loaded at boot) nctl create app my-app --env=DATABASE_URL:"postgres://user:password@host/db";REDIS_URL:"redis://host";SECRET_KEY_BASE:"abc123" ``` For an existing application: ```bash # Build variables (only during build phase) nctl update app my-app --build-env=NODE_ENV:"production";SENTRY_AUTH_TOKEN:"xyz123" # Runtime variables (loaded at boot) nctl update app my-app --env=DATABASE_URL:"postgres://user:password@host/db";REDIS_URL:"redis://host";SECRET_KEY_BASE:"abc123" ``` If you are coming from Heroku, you can use the script [here](migrating-from-other-platforms.md#retrieving-environment-variables) to retrieve your environment variables in the format required by Deploio. \== Cockpit You can also configure environment variables in the Cockpit. This is useful for quickly setting up environment variables for your application, and viewing the current environment variables in a more user-friendly way. You can navigate to your **Application** page, and then either click on the **Configuration** tab, or the **Edit** button on the top right of the page. In both cases, the environment variables are split into two sections: **Environment Variables** and **Build Environment Variables**. Here you can add, edit, or delete environment variables, as well as edit in a YAML format. \== .deploio.yaml Environment variables can also be configured in the `.deploio.yaml` file. However, the settings specified directly in the application configuration will take precedence over the settings in the `.deploio.yaml` file. ```yaml # Build variables buildEnv: - name: NODE_ENV value: "production" # Runtime variables env: - name: DATABASE_URL value: "postgres://user:password@host/db" ``` \== Procfile Environment variables cannot be configured in the Procfile. Please use one of the other methods instead. ::: #### Debugging Environment Variables Several parts of Deploio might inject env variables into your application (e.g. [connected services](https://docs.nine.ch/docs/deplo-io/configuration/deploio-connecting-to-services/#injected-environment-variables) or [buildpacks](https://docs.nine.ch/docs/deplo-io/configuration/buildpack-stacks)). If you want to know what env variables are used for real during runtime, there is no other way than to look into the running application: ```bash nctl exec app my-app -- env ``` ### Basic Authentication Protect non-production environments (like staging) with HTTP Basic Auth, configurable directly in the Cockpit and built in to Deploio. ::: info Basic Auth Implementation Basic auth credentials are generated and managed by Deploio's controllers. The password is stored as a Kubernetes secret and referenced by the ingress configuration. You cannot set the password manually, but you can rotate it as frequently as needed using the `--change-basic-auth-password` command. ::: :::tabs key:config \== nctl Basic authentication can be enabled using the `nctl` CLI tool. ```bash # Enable basic auth (you can also run update app with the same command) nctl create app my-app --basic-auth # Get credentials nctl get app my-app --basic-auth-credentials # Rotate credentials nctl update app my-app --change-basic-auth-password ``` \== Cockpit Navigate to your **Application** page and click the **Edit** button. Under **Configuration**, you can enable/disable basic authentication. Once enabled, you can also get the credentials by clicking the **Show** button on the **Application** page. \== .deploio.yaml As noted previously, any configuration set in the Cockpit or `nctl` will take precedence over the configuration in `.deploio.yaml`. ```yaml # Enable basic authentication enableBasicAuth: true ``` \== Procfile Basic authentication cannot be configured in the Procfile. Use one of the other methods instead. ::: ### Web Application Configuration There are a number of configuration options for your web application. #### Port Configuration Your application needs to expose a TCP/IP port to handle HTTP requests. The port configuration works as follows: 1. **Application Level**: * Your application will use a default port (e.g., in Rails this is port 3000 for Puma or 8080 for the buildpack default) * You can configure this in your application (e.g., in Rails you can set this in `config/puma.rb`) * If configured, the application will use this port * If not configured, the application will use the `PORT` environment variable 2. **Deploio Level**: * You can only configure the `PORT` environment variable * This can be done either via `--port` in nctl or through runtime environment variables in Cockpit * The actual port your application listens on internally is determined by your application's configuration 3. **External Access**: * All Deploio applications are accessible externally only on port 443 (HTTPS) * This is handled by Deploio's ingress-nginx layer * The ingress layer routes traffic based on the HTTP host header to the correct internal service * No other external ports are supported ::: info Port Configuration Best Practices The recommended approach is to let your application use its default port (e.g., 3000 for Rails/Puma) and configure the `PORT` environment variable in Deploio if you need to change it. The internal port configuration is abstracted away from end users, as all external access is handled through HTTPS on port 443. ::: :::tabs key:config \== nctl Set the internal port using the `--port` flag: ```bash # Set port during app creation nctl create app my-app --port=3000 # Update port for existing app nctl update app my-app --port=3000 ``` \== Cockpit Navigate to your **Application** page and click the **Edit** button. Under **Configuration**, you can set the port number. \== .deploio.yaml ```yaml # Set the internal port port: 3000 ``` \== Procfile Port cannot be configured in the Procfile. Use one of the other methods instead. ::: #### Replicas Configure how many instances of your application should run. :::tabs key:config \== nctl Set the number of replicas using the `--replicas` flag: ```bash # Set replicas during app creation nctl create app my-app --replicas=3 # Update replicas for existing app nctl update app my-app --replicas=3 ``` \== Cockpit Navigate to your **Application** page and click the **Edit** button. Under **Configuration**, you can set the number of replicas. \== .deploio.yaml ```yaml # Set the number of replicas replicas: 3 ``` \== Procfile Replicas cannot be configured in the Procfile. Use one of the other methods instead. ::: #### Size Configure the compute resources allocated to your application. You can view the available sizes and more information [here](#resource-sizing). :::tabs key:config \== nctl Set the size using the `--size` flag: ```bash # Set size during app creation nctl create app my-app --size=standard-2 # Update size for existing app nctl update app my-app --size=standard-2 ``` \== Cockpit Navigate to your **Application** page and click the **Edit** button. Under **Configuration**, you can select the size from the dropdown menu. \== .deploio.yaml ```yaml # Set the size size: standard-2 ``` \== Procfile Size cannot be configured in the Procfile. Use one of the other methods instead. ::: ### Resource Sizing Each Deploio app, along with its corresponding jobs (for example, deploy or worker job), receives a standard amount of resources (RAM, CPU and Ephemeral Storage) when it is run. These resources are assigned individually and are not shared. If the app's or job's resource usage exceeds its standard limit, Nine reserves the right to terminate the app. Every replica will get the documented amount of resources. Meaning, the amount of resources is not shared between replicas. #### Available Sizes | Size | Standard RAM | CPU | Ephemeral Storage | |------------|--------------|---------|-------------------| | micro | 256 MiB | ⅛ Core | 2 GiB | | mini | 512 MiB | ¼ Core | 2 GiB | | standard-1 | 1 GiB | ½ Core | 2 GiB | | standard-2 | 2 GiB | ¾ Core | 2 GiB | | standard-4 | 4 GiB | 1 ½ Core | 2 GiB | Prices for each Deploio instance size can be found on the [pricing page](https://deplo.io/pricing). ### Deploy Job A Deploy Job is a way to run a command before a new release is deployed. This is useful for running database migrations, or other setup tasks. The deployment will only continue if the job finished successfully. ::: info Where Deploy Jobs Run Deploy jobs run on the same server as your application, using the same resources and environment. They are executed during the deployment process, before the new version of your application is started. This means they share the same compute resources (CPU, memory) as defined by your application's size. ::: #### Configuration We will see how to configure the extra options using each method, but here is an overview of the options: | Option | Description | Default | Limits | |------------------------|-----------------------------------------------------------------------------------------------------------------|------------|-------------------| | `--deploy-job-name` | Name of the deploy job. The deployment will only continue if the job finished successfully. | (required) | - | | `--deploy-job-command` | Command to execute before a new release gets deployed. No deploy job will be executed if this is not specified. | (required) | - | | `--deploy-job-retries` | How many times the job will be restarted on failure. | 3 | Max: 5 | | `--deploy-job-timeout` | Timeout of the job. | 5m | Min: 1m, Max: 30m | :::tabs key:config \== nctl ```bash # Create a deploy job (you can also run update app with the same command for an existing app) nctl create app my-app \ --deploy-job-name="migrate" \ --deploy-job-command="rake db:migrate" \ --deploy-job-retries=3 \ --deploy-job-timeout=5m ``` \== Cockpit Navigate to your **Application** page and click the **Edit** button. Under **Jobs**, you can enable a new **Deploy Job**. This requires a command, which will be executed by a bash shell before a new release is deployed. You also need to specify the number of retries and a timeout. \== .deploio.yaml ```yaml deployJob: name: "database-migration" command: "rake db:prepare" retries: 3 timeout: 5m ``` \== Procfile Deploy job cannot be configured in the Procfile. Use one of the other methods instead. ::: #### Monitoring :::tabs key:config \== nctl If a deploy job fails, the associated release will be set to failed and the previous release will continue to run if there was one to begin with. To see the detailed status of a deploy job you can get the full release: ```bash $ nctl get releases my-app -o yaml [...] status: atProvider: deployJobStatus: exitTime: 2023-07-18T11:01:47Z name: my-app-deploy-job reason: backoffLimitExceeded startTime: 2023-07-18T11:00:58Z status: failed releaseStatus: failure ``` At the bottom of the release you can see the status and it will show in detail when and how a deploy job failed. In addition to the status, the deploy job's log will be written to the normal app log and can be accessed using the `nctl logs app` command. \== Cockpit You can view the **Deploy Job** in the **Jobs** tab. In this tab, you can view the configuration and the status of the job. \== .deploio.yaml Deploy jobs can only be monitored in the Cockpit or via the `nctl` command. \== Procfile Deploy jobs can only be monitored in the Cockpit or via the `nctl` command. ::: ### Worker Jobs Worker jobs are background processes that run alongside your main application using a job system (sometimes called message queue or job queue). They are useful for handling tasks like processing queues, sending emails, or running scheduled tasks. Worker jobs share the app's image and environment but have a different entry point, e.g., for task scheduling. ::: info Where Worker Jobs Run Worker jobs run on their own dedicated server, separate from your main application. This means they can be scaled independently and have their own resource allocation. You can configure the size of each worker job to match its resource needs, which can be different from your main application's size. See the [Resource Sizing](#resource-sizing) section for available sizes and their specifications. ::: #### Configuration We will see how to configure the extra options using each method, but here is an overview of the options: | Option | Description | Default | Limits | |------------------------|----------------------------------------|------------|-------------------------------------------------------------| | `--worker-job-name` | Name of the worker job. | (required) | - | | `--worker-job-command` | Command to execute for the worker job. | (required) | - | | `--worker-job-size` | Size of the worker job. | "micro" | See [Resource Sizing](#resource-sizing) for available sizes | :::tabs key:config \== nctl ```bash # Create a worker job (works for both create and update app) nctl create app my-app \ --worker-job-name="sidekiq" \ --worker-job-command="bundle exec sidekiq" \ --worker-job-size="standard-2" ``` \== Cockpit Navigate to your **Application** page and click the **Edit** button. Under **Jobs**, you can create multiple **Worker Jobs**. Each job requires a name, a command, and the size of the worker to run the job. \== .deploio.yaml ```yaml workerJobs: - name: "sidekiq" command: "bundle exec sidekiq" size: "standard-2" ``` \== Procfile Worker jobs cannot be configured in the Procfile. Use one of the other methods instead. ::: #### Monitoring :::tabs key:config \== nctl The simplest way to view the status of a worker job with `nctl` is to use the `-o stats` command: ```bash $ nctl get app my-app -o stats ``` Additionally, the logs of the worker jobs can be accessed by viewing the app logs using the `nctl logs app` command. \== Cockpit You can view the **Worker Jobs** in the **Jobs** tab. In this tab, you can view the configuration and the status of the jobs. \== .deploio.yaml Worker jobs can only be monitored in the Cockpit or via the `nctl` command. \== Procfile Worker jobs can only be monitored in the Cockpit or via the `nctl` command. ::: ### Scheduled Jobs Scheduled jobs are commands that run at regular intervals based on a predefined schedule. They are useful for tasks like database cleanup, sending reports, or any other recurring tasks. ::: info Where Scheduled Jobs Run Scheduled jobs run on their own dedicated server, similar to worker jobs. Each scheduled job can be configured with its own size to match its resource requirements. The jobs are executed according to their schedule, and each execution runs in an isolated environment to prevent interference with other jobs or your main application. See the [Resource Sizing](#resource-sizing) section for available sizes and their specifications. ::: #### Configuration We will see how to configure the extra options using each method, but here is an overview of the options: | Option | Description | Default | Limits | |----------------------------|-------------------------------------------|----------------------------|-------------------------------------------------------------| | `--scheduled-job-name` | Name of the scheduled job. | (required) | - | | `--scheduled-job-command` | Command to execute for the scheduled job. | (required) | - | | `--scheduled-job-schedule` | Cron schedule for the job. | `* * * * *` (every minute) | - | | `--scheduled-job-size` | Size of the scheduled job. | "micro" | See [Resource Sizing](#resource-sizing) for available sizes | :::tabs key:config \== nctl ```bash # Create a scheduled job (works for both create and update app) nctl create app my-app \ --scheduled-job-command="bundle exec rails runner" \ --scheduled-job-name=scheduled-1 \ --scheduled-job-size=micro \ --scheduled-job-schedule="* * * * *" ``` \== Cockpit Navigate to your **Application** page and click the **Edit** button. Under **Jobs**, you can create multiple **Scheduled Jobs**. Each job requires a name, a command, a schedule, and the size of the worker to run the job. You can also specify the retries and timeout for the job. \== .deploio.yaml ```yaml scheduledJobs: - command: sleep 60; date name: scheduled-1 retries: 0 schedule: "*/5 * * * *" size: micro timeout: 5m0s ``` \== Procfile Scheduled jobs cannot be configured in the Procfile. Use one of the other methods instead. ::: #### Monitoring If a scheduled job fails, the associated release will NOT be set to failed and continue running. :::tabs key:config \== nctl To see the detailed status of a scheduled job you can get the full release: ```bash $ nctl get releases my-app -o yaml [...] status: atProvider: scheduledJobStatus: - name: scheduled-1 replicaObservation: - replicaName: go-scheduled-scheduled-1-29038220 status: succeeded ``` At the bottom of the release you can see the status and it will show in detail the status of the scheduled job. In addition to the status, the scheduled job's log will be written to the normal app log and can be accessed using the `nctl logs app` command. \== Cockpit You can view the **Scheduled Jobs** in the **Jobs** tab. In this tab, you can view the configuration and the status of the jobs. In addition to the status, the scheduled job's log will be written to the normal app log and can be viewed in the **Logs** tab. \== .deploio.yaml Scheduled jobs can only be monitored in the Cockpit or via the `nctl` command. \== Procfile Scheduled jobs can only be monitored in the Cockpit or via the `nctl` command. ::: --- --- url: 'https://guides.deplo.io/user-guide/configuring-your-database.md' description: >- Comprehensive guide for creating and managing PostgreSQL and MySQL databases on Deploio including Economy and Business tiers, configuration, backups, monitoring, and troubleshooting. --- # Configuring your Database Deploio offers managed MySQL and PostgreSQL databases across two tiers, each designed for different use cases. For more information visit the [database product page](https://nine.ch/products/databases/) or the [technical reference](https://docs.nine.ch/docs/on-demand-services/). ### Choosing a tier | | Economy | Business | |----------------------------|-----------------------------------------|--------------------------------| | **Best for** | Development, testing, low-traffic sites | High-traffic sites | | **Resources** | Multi-tenant | Dedicated instance | | **Storage** | Up to 10 GB | 20 GB+ (auto-expanding) | | **Databases per instance** | 1 | Multiple | | **Custom configuration** | No | Limited | | **Backups** | Daily (S3 storage) | Daily (configurable retention) | ### Protecting Database Access All database instances only accept TLS-encrypted connections. Depending on the client or library, you may need to explicitly enable TLS. The TLS certificate is self-signed, so you may also need to disable certificate hostname validation. See the [technical reference](https://docs.nine.ch/docs/on-demand-services/mysql/economy#tls) for more details. For **Business** tier instances, you must set up SSH key authentication to access the database server directly. Pass the public key via the `--ssh-keys` flag when creating the database. In addition, you can restrict access by IP address using the `--allowed-cidrs` flag. Access from Nine's Kubernetes products (NKE, GKE) and Deploio is already allowed by default. ## Economy tier Databases in the Economy tier run in a logically separated tenant on a shared, multi-tenant environment managed by Nine — ideal for development, testing, and low-traffic applications. They start fast, making them a good fit for automated testing pipelines e.g. ::: info Manual Backup Restore The Economy tier is still missing a one-click backup restore feature. You currently need to open a [support ticket with Nine](mailto:support@nine.ch) for restore. We'll make this as easy as a button-click soon. ::: #### Packages The package is automatically selected based on the current database size. Storage is capped at 10 GB — if you need more, migrate to a Business tier instance. ::: info Manual Work Migration from Economy to Business is a manual step currently. We'll make this as easy as a button-click soon. ::: | Package | Max Storage | Max Connections | |---------|-------------|-----------------| | S | 1 GB | 20 | | M | 5 GB | 20 | | L | 10 GB | 20 | #### Limitations * One database per instance (the database name matches the username) * No dedicated resources — runs on shared infrastructure * No custom configuration options (e.g. no IP allowlist) * No SSH access to the instance * Storage cannot exceed 10 GB ### Creating an Economy database :::tabs key:db \== PostgreSQL ```bash nctl create postgresdatabase {DATABASE_NAME} ``` Optional flags: * `--collation` — Set the collation (default: `C.UTF-8`) * `--location` — Set the data center location Retrieve connection details: * **FQDN**: `nctl get postgresdatabase {DATABASE_NAME}` * **User**: `nctl get postgresdatabase {DATABASE_NAME} --print-user` * **Password**: `nctl get postgresdatabase {DATABASE_NAME} --print-password` * **Connection string**: `nctl get postgresdatabase {DATABASE_NAME} --print-connection-string` Connect to your database: ```bash psql -d "$(nctl get postgresdatabase {DATABASE_NAME} --print-connection-string)" ``` \== MySQL ```bash nctl create mysqldatabase {DATABASE_NAME} ``` Optional flags: * `--character-set` — Set the character set (default: `utf8mb4_unicode_ci` / `utf8mb4`) * `--location` — Set the data center location Retrieve connection details: * **FQDN**: `nctl get mysqldatabase {DATABASE_NAME}` * **User**: `nctl get mysqldatabase {DATABASE_NAME} --print-user` * **Password**: `nctl get mysqldatabase {DATABASE_NAME} --print-password` Connect to your database: ```bash mysql -h {FQDN} -u {USER} -p ``` ::: ### Backups Backups are created daily and stored in S3-compatible object storage. To restore a PostgreSQL Economy backup: 1. Find the corresponding bucket for your database backup ```bash nctl get bucket ``` 2. Get the S3 credentials for the bucket user with the same name as the bucket ```bash nctl get bucketuser {backup_bucket_name} --print-credentials ``` 3. Download the backup using any S3-compatible client tool, e.g. `awscli`, see the [Nine technical reference](https://docs.nine.ch/docs/on-demand-services/postgresql/economy#backups) for more details ## Business tier Business databases provide dedicated, isolated instances with their own resources — ideal for high-traffic sites. You get full user and database management, configurable backups, and automatic storage expansion. ### Database creation settings There are a number of configurations you can apply when creating a Business database. Run `--help` for details, e.g. `nctl create mysql --help`. #### Name The name of the instance can be freely chosen, but must be unique. Once created, the name cannot be changed. #### Location Instances can be created in the following data center locations: | Location | Data Center | |----------|-------------| | `nine-cz42` | ColoZüri 4.2, Altstetten, Zürich | | `nine-es34` | NTT Zürich 1, Rümlang | The location cannot be changed after creation. #### Version The database version must be selected when creating the instance and cannot be changed later. Available versions and their support periods are listed in the database-specific sections below. #### Machine type | Machine Type | Virtual CPU (VCPU) | RAM | Storage Space | Monthly Fees | |--------------|---------------------|--------|---------------|--------------| | nine-db-xs | 2 | 4 GB | 20 GB | CHF 65 | | nine-db-s | 4 | 8 GB | 20 GB | CHF 97 | | nine-db-m | 4 | 12 GB | 20 GB | CHF 117 | | nine-db-l | 6 | 16 GB | 20 GB | CHF 149 | | nine-db-xl | 8 | 24 GB | 20 GB | CHF 201 | | nine-db-xxl | 10 | 32 GB | 20 GB | CHF 253 | Additional storage space per 10 GB: CHF 1.50 per month. Machine types can be changed after creation. After an adjustment, the database instance will be restarted and will be unavailable for a few minutes. #### Allowed IP addresses IPv4 addresses and address ranges from which connections to the service can be established. Access from our Kubernetes products NKE (Nine Kubernetes Engine) and GKE (Google's Kubernetes Engine), as well as from deplo.io, is already enabled. The access restriction can be adjusted at any time. Adjustments are made non-disruptively moments after the form is submitted. We can set the allowed CIDRs by passing the `--allowed-cidrs={CIDR}` flag. #### Backups The backup retention period in days can be selected between 0 and 365 days by passing the `--keep-daily-backups={X}` flag. If 0 days is selected, the backup routine will be disabled and all existing backups will be deleted. The default retention period is 10 days. Please note that the storage space requirement increases if the local retention period is long. This may result in higher instance costs. For more information about backing up your databases on a daily basis, accessing the backups, and how to create your own backups if needed, see the section about [backups](#backup-and-restore). #### Accessing backups Configure the public keys to access the database backups via SSH. The keys can be adjusted at any time. These can be set via the `--ssh-keys` flag or the `--ssh-keys-file` flag. ### Database specific creation settings :::tabs key:db \== PostgreSQL #### Versions available In the following table you can find the support period of each PostgreSQL version: | PostgreSQL Version | Support End | |--------------------|-------------------| | 17 | November 08, 2029 | | 16 | November 09, 2028 | | 15 | November 11, 2027 | #### Extensions Nine provides a variety of extensions that you can activate as needed. The following extensions are available: * address\_standardizer * address\_standardizer\_data\_us * btree\_gin * btree\_gist * citext * cube * dict\_int * earthdistance * fuzzystrmatch * hstore * intarray * isn * lo * ltree * pg\_prewarm * pg\_stat\_statements * pg\_trgm * pgcrypto * plpgsql * postgis * postgis\_tiger\_geocoder * postgis\_topology * seg * tablefunc * tcn * tsm\_system\_time * tsm\_system\_rows * unaccent * uuid-ossp * vector #### Collations PostgreSQL uses ICU (International Components for Unicode) collations, which can be customized per database, schema, or column. The default collation is typically `C.UTF-8`. When migrating the database, ensure your application's collation settings are compatible with your target PostgreSQL version. Different versions may handle text sorting and comparison differently, which could affect your application's behavior. ### Creating the Database Considering the creation settings above, we run the following command to create the database server: ``` nctl create postgres {DATABASE_NAME} \ --postgres-version={X} \ --machine-type=nine-db-s \ --allowed-cidrs=0.0.0.0/0 # all IP ranges \ --ssh-keys={PUBLIC_KEY} ``` Please adjust the flags as you need. We can now access the server using the FQDN and generated user and password. We can find this information as follows: * **FQDN**: Run `nctl get postgres {DATABASE_NAME}` * **User**: Run `nctl get postgres {DATABASE_NAME} --print-user` * **Password**: Run `nctl get postgres {DATABASE_NAME} --print-password` Now we want to create the database on the server. We can run the following command: ``` createdb -U dbadmin -h {FQDN} {DATABASE_NAME} ``` You will be prompted to enter the password. We can check that this database was created by entering the server using `psql -U dbadmin -h {FQDN} -d postgres` and then running the command `\l` to list the databases on the server. ### Interacting with databases ##### Connecting The connection information (FQDN, user, and password) for your instance can be found in Cockpit under Access Information. The database servers are accessible via their standard ports. We can also find this information via the `nctl` command line tool: * **FQDN**: Run `nctl get postgres {DATABASE_NAME}` * **User**: Run `nctl get postgres {DATABASE_NAME} --print-user` * **Password**: Run `nctl get postgres {DATABASE_NAME} --print-password` The instance will only accept TLS connections. Depending on the client or library, you may need to explicitly enable TLS. ```bash psql -h FQDN -d postgres -U dbadmin # at first you can use the default database 'postgres' to be able to connect. ``` ##### Basic commands Creating a new database named `app_prod`: ``` postgres=> CREATE DATABASE app_prod; ``` Creating a new user named `app_prod`: ``` postgres=> CREATE USER app_prod WITH PASSWORD 'strongpassword'; ``` You can also use the `--pwprompt` flag to be prompted for the password, or the `--interactive` flag to configure the user interactively. Otherwise, the password will be visible in the command and on screen. You may also want to create a [superuser](https://www.postgresql.org/docs/current/role-attributes.html), which can be done by using the `--superuser` flag or via the interactive prompt. You can see more information about the flags when creating a user in the [official postgres documentation](https://www.postgresql.org/docs/current/app-createuser.html). Granting the user `app_prod` privileges to the database `app_prod`: ``` postgres=> GRANT ALL ON app_prod TO app_prod; ``` > For granting more specified privileges, find the details in the official postgres documentation: DDL privileges. Changing the user `app_prod`'s password: ``` postgres=> ALTER USER app_prod WITH PASSWORD 'newstrongpassword'; ``` Deleting the database `app_prod`: ``` postgres=> DROP DATABASE app_prod; ``` Deleting the user `app_prod`: ``` postgres=> DROP USER app_prod; ``` Use the official Postgres documentation for additional info about user and database management. \== MySQL #### Versions available Nine currently provides On-Demand MySQL environments with MySQL 8 only. #### Long Query Time The "Long Query Time" specifies the time in seconds after which the MySQL service considers the execution of a query to be slow and logs the query. #### Min Word Length This value configures the minimum length of a word that MySQL will use for full text search. Nine sets the value chosen here for both `ft_min_word_len` (MyISAM Storage Engine, Legacy) and `innodb_ft_min_token_size` (InnoDB Storage Engine). #### Character Set The charset is customizable. From experience, the default values `utf8mb4_unicode_ci` / `utf8mb4` cover most needs. Before considering customizing these values, please consult the MySQL documentation: [Character Sets and Collations in MySQL](https://dev.mysql.com/doc/refman/8.0/en/charset-mysql.html). #### Collations MySQL 8.0 uses the `utf8mb4_0900_ai_ci` collation by default, which is based on Unicode 9.0.0. This is different from older MySQL versions which use `utf8mb4_unicode_ci` (based on Unicode 4.0.0). When migrating between MySQL versions, ensure your application's collation settings are compatible with your target MySQL version. You may need to adjust your application's text sorting and comparison behavior accordingly. #### Transaction Isolation Nine recommends not making any adjustment to the selected default value unless absolutely necessary due to application requirements. Be sure to consult the MySQL documentation in advance and familiarize yourself with the related implications: [Transaction Isolation Levels](https://dev.mysql.com/doc/refman/8.0/en/innodb-transaction-isolation-levels.html). #### SQL Modes The SQL Mode should also only be adjusted if the application absolutely requires it. Nine uses the default values set by Oracle for MySQL 8. Oracle provides documentation and FAQ about SQL Modes in the following articles: * [MySQL 8.0 FAQ: Server SQL Mode](https://dev.mysql.com/doc/refman/8.0/en/faqs-sql-modes.html) * [Server SQL Modes](https://dev.mysql.com/doc/refman/8.0/en/sql-mode.html) #### Extensions MySQL does not support extensions in the same way as PostgreSQL (via `CREATE EXTENSION`). However, many advanced features are either built into the core engine or available via optional server plugins. You don't need to enable these manually — they are either available by default or configurable at runtime (via SQL or server settings). > To inspect available plugins on your instance, you can run: > > ```sql > SHOW PLUGINS; > ``` Let us know if you need help enabling specific capabilities or configuring advanced features in your MySQL setup. ### Creating the Database Considering the creation settings above, we run the following command to create the database server: ``` nctl create mysql {DATABASE_NAME} \ --mysql-version={X} \ --machine-type=nine-db-s \ --allowed-cidrs={IP_ADDRESS}/0 \ --ssh-keys={PUBLIC_KEY} ``` Please adjust the flags as you need. We can now access the server using the FQDN and generated user and password. We can find this information as follows: * **FQDN**: Run `nctl get mysql {DATABASE_NAME}` * **User**: Run `nctl get mysql {DATABASE_NAME} --print-user` * **Password**: Run `nctl get mysql {DATABASE_NAME} --print-password` Now we want to create the database on the server. We can run the following commands: 1. **Connect to the server:** ```bash mysql -h {FQDN} -u dbadmin -p ``` You will be prompted to enter the password. 2. **Create a new database from the MySQL prompt:** ```sql CREATE DATABASE my_app_db; ``` 3. **List all databases to confirm:** ```sql SHOW DATABASES; ``` ### Interacting with databases ##### Connecting The connection information (FQDN, user, and password) for your instance can be found in Cockpit under Access Information. The database servers are accessible via their standard ports. We can also find this information via the `nctl` command line tool: * **FQDN**: Run `nctl get mysql {DATABASE_NAME}` * **User**: Run `nctl get mysql {DATABASE_NAME} --print-user` * **Password**: Run `nctl get mysql {DATABASE_NAME} --print-password` The instance will only accept TLS connections. Depending on the client or library, you may need to explicitly enable TLS. The TLS certificate in use is self-signed. In addition to enabling TLS transport encryption, you might need to disable certificate validation. ```bash mysql -h FQDN -u dbadmin -p # You will be prompted to enter the password ``` ##### Basic commands Connecting to your Database: ``` mysql -h FQDN -u dbadmin -p ``` Creating a new database named app\_prod: ``` mysql> CREATE DATABASE app_prod; ``` Creating a new user named `app_prod`: ``` mysql> CREATE USER 'app_prod' IDENTIFIED BY 'strongpassword'; ``` Granting the user `app_prod` privileges to the database `app_prod`: ``` mysql> GRANT ALL ON app_prod.* TO 'app_prod'@'%'; ``` > For granting more specified privileges, find the details in the official MySQL documentation: Summary of Available Privileges. Changing the user `app_prod`'s password: ``` mysql> ALTER USER app_prod IDENTIFIED BY 'newstrongpassword'; ``` Deleting the database `app_prod`: ``` mysql> DROP DATABASE app_prod; ``` Deleting the user `app_prod`: ``` mysql> DROP USER app_prod; ``` Use the official MySQL documentation for additional info about user and database management. ::: *** ### Monitoring for health and performance Deploio database instances run on Nine's managed infrastructure. Nine monitors basic infrastructure-level availability, however you are responsible for observing database-level performance and load. You can view the current status of the system [here](https://status.nine.ch/). Nine monitors the instance with a monitoring system 24x7. In the event of a malfunction, an (on-call) technician from Nine is automatically alerted and restores proper operation as quickly as possible. You can also view the current status of a database via the Cockpit, as well as information such as version, backup retention policy and "Allowed IP Addresses". This information can help when trying to assess connection issues. > ⚠️ Resource saturation (e.g., full CPU/memory/disk) is **not considered a malfunction**. You are responsible for monitoring performance and scaling your instance as needed. #### What is Monitored by Nine Nine monitors the **availability** and **infrastructure health** of the database node, such as: * Instance accessibility (e.g. FQDN ping) * Hardware failures * Backup completion status * Disk thresholds (for automatic storage expansion) However, **application-level metrics like query latency, connection count, or CPU load** are not exposed via Cockpit today. This feature is currently WIP and will be available soon. #### What You Can Monitor Yourself :::tabs key:db \== PostgreSQL To monitor your PostgreSQL database performance, you can connect via `psql` and use built-in extensions: * `pg_stat_statements` – View expensive queries by total time * `pg_stat_activity` – List active sessions and queries * `pg_stat_bgwriter` – Monitor I/O activity and checkpoint behavior Example to get top slow queries: ```sql SELECT * FROM pg_stat_statements ORDER BY total_time DESC LIMIT 5; ``` To monitor connections: ```sql SELECT * FROM pg_stat_activity; ``` ##### Best Practices for PostgreSQL * Enable `pg_stat_statements` at instance creation or shortly after * Use tools like `psql`, pgAdmin, or DBeaver for live inspection * Log slow queries from your app for long-term insights * Regularly check backup status and instance disk growth * Scale machine type via `nctl update` if your app outgrows the current size \== MySQL To monitor your MySQL database performance, you can connect via `mysql` and run: ```bash mysql -u dbadmin -p -h {FQDN} ``` Useful commands: * View active queries: ```sql SHOW PROCESSLIST; ``` * View general performance stats: ```sql SHOW GLOBAL STATUS; ``` * Check uptime, queries per second, open connections: ```sql SHOW STATUS LIKE 'Uptime'; SHOW STATUS LIKE 'Threads_connected'; SHOW STATUS LIKE 'Questions'; ``` ##### Best Practices for MySQL * Enable slow query logging at the application level * Use tools like `mysql`, pgAdmin, or DBeaver for live inspection * Log slow queries from your app for long-term insights * Regularly check backup status and instance disk growth * Scale machine type via `nctl update` if your app outgrows the current size ::: *** ### Backup and Restore Nine backs up Business databases daily between 02:00 and 03:00 UTC. These backups are kept locally for 10 days (configurable) and on a remote backup system for seven days. Backups are stored in the `/home/dbadmin/backup` directory. All backups are versioned in directories with the following time scheme (example, exact timestamp will vary): `2022-11-18-0134`. `/home/dbadmin/backup/latest` always points to the latest backup. Backups are stored in the `customer` directory. The database schema can be found in the `structure` directory. ##### Create additional backups Additional backups can be created by running: :::tabs key:db \== PostgreSQL ``` dbadmin@managedvirtualmachine-xxxxxxx:~ $ sudo nine-postgresql-backup 2022-11-18T09:54:19+01:00 Dumped and compressed database 'frontend_production' in 53 seconds 2022-11-18T09:55:04+01:00 Dumped and compressed database 'frontend_staging' in 45 seconds ``` \== MySQL ``` dbadmin@managedvirtualmachine-xxxxxxx:~ $ sudo nine-mysql-backup 2022-11-18T09:54:19+01:00 Dumped and compressed database 'frontend_production' in 53 seconds 2022-11-18T09:55:04+01:00 Dumped and compressed database 'frontend_staging' in 45 seconds ``` ::: ##### Downloading a backup to your local machine To download a backup to your local machine, you can, for example, use `rsync`: ```bash rsync -v dbadmin@{FQDN}:~/backup/postgresql/latest/customer/{DATABASE_NAME}/{DATABASE_NAME}.zst ./backup.zst ``` ##### Storage requirements of the backups The backup routine creates compressed backups. Depending on the size of the database, this may still result in backups that require a lot of disk space. To ensure that sufficient disk space is always available, the On Demand database environments have a mechanism that automatically monitors and performs a [disk space expansion if required](#automatic-storage-space-expansion). ##### Number of backups kept The number of backups kept can be adjusted via Cockpit. The duration of the retention period can be freely selected between one and 365 days. Please note that a long retention period requires more storage space, which may result in additional costs. ##### Disabling backups To disable backups, the retention time can be adjusted to `0`. In this case, the creation of further backups is deactivated. All backups already created will be **deleted** shortly after the adjustment. ##### Access to the created backups Using the system user `dbadmin` you can access the created backups via an SSH connection. SSH access for the user is controlled by storing an SSH key in Cockpit. ##### Restoring and working with the created backups The backup routine used is the same as the one we use for our managed servers. We have described how to work with the backups as well as more information about restoring backups in the following support articles: * PostgreSQL Backups and Restore * MySQL Backups and Restore #### Automatic storage space expansion To provide the most robust environment possible, the available storage space is monitored at 5 minute intervals. If our monitoring detects that the available storage space falls below a threshold, an expansion of the storage quota is automatically performed. ##### Thresholds For a total storage size below 50 GB, the threshold is 5 GB of free storage space. For a total storage size above 50 GB, the threshold is 10% free storage space. ##### Expansion of the storage space The expansion of the storage space is done automatically in steps of 25 GB. ##### Reduction of storage space It is not currently possible to reduce the disk size of database instances. The only way to reduce disk usage is to download a backup of the current instance and restore it to a new instance. ##### Billing of the storage space expansion The additional storage space is charged automatically. --- --- url: 'https://guides.deplo.io/php/database.md' description: >- Instructions for creating and configuring PostgreSQL or MySQL databases for PHP applications including Doctrine integration, migrations, and connection troubleshooting. --- # Create a Database for Your PHP Application ::: info In this guide, we will show you how to create a database for your PHP application using Deploio. You can see more information on databases [here](/user-guide/configuring-your-database.md). Should you wish to migrate an already existing database from elsewhere, you can view this section in the documentation [here](/user-guide/migrating-from-other-platforms.md). ::: ## Choose a tier Deploio offers two database tiers. See the [database guide](/user-guide/configuring-your-database.md) for full details. | | Economy | Business | |----------------------------|-----------------------------------------|--------------------------------| | **Best for** | Development, testing, low-traffic sites | Production, high-traffic sites | | **Databases per instance** | 1 | Multiple | | **Storage** | Up to 10 GB | 20 GB+ (auto-expanding) | | **Resources** | Shared (multi-tenant) | Dedicated instance | ## Create the database ::: tip To ensure the database resource gets allocated to the correct project, you should switch to the correct project context: ```bash nctl auth set-project my-project ``` Alternatively, you can specify the project name with the `-p, --project` flag in the following commands. ::: :::tabs key:db \== PostgreSQL #### Economy Create a PostgreSQL database: ```bash nctl create postgresdatabase {NAME} ``` Add the database as a service reference to your application: ```bash nctl update app {APP_NAME} \ --service db=postgresdatabase/{NAME} ``` If the application is already running, create a new release so the injected service variables become available: ```bash nctl update app {APP_NAME} --retry-release ``` The following environment variables have been injected into your application: | Variable | Description | | :--- | :--- | | `NINE_PGDB__FQDN` | Hostname. Uses private networking DNS when private networking is configured; otherwise the public hostname. | | `NINE_PGDB__PORT` | Port `(always 5432)`. | | `NINE_PGDB__USER` | Database name (same as the name assigned at creation). | | `NINE_PGDB__PASSWORD` | Password. | | `NINE_PGDB__CA_CERT` | CA certificate. Only injected when a CA certificate is present. | | `NINE_PGDB__DSN` | Full PostgreSQL connection URI `(postgres://user:pass@host:port/dbname)`. | Where `` is the reference name you assigned in `--service =..`, uppercased with non-alphanumeric characters replaced by `_`. For example, the previously used reference name `db` becomes `DB`. See the [technical reference](https://docs.nine.ch/docs/deplo-io/configuration/deploio-connecting-to-services) for more info on service references. #### Business To create a Postgres database server for your PHP application, you can use the `nctl create` command like this: ```bash nctl create postgres {NAME} \ --postgres-version=16 \ --machine-type=nine-db-s \ --location=nine-cz42 ``` Further details on the flags can be found in the manual by running `nctl create postgres --help`. You can now access the server using the **fully-qualified domain name (FQDN)** and generated user and password. Retrieve this information by running: ```bash $ nctl get postgres {NAME} PROJECT NAME FQDN LOCATION MACHINE TYPE my-project {NAME} {NAME}.1234567.postgres.nineapis.ch nine-cz41 nine-db-s $ nctl get postgres {NAME} --print-user dbadmin $ nctl get postgres {NAME} --print-password ...password... ``` ## Access to the server By default, your database server is only accessible from applications running in Deploio. If you want to access the database server from your local machine or some other location, you need to configure network exceptions with the `--allowed-cidrs` option. To allow all IPs, you would use the following parameter: ```bash nctl update postgres {NAME} --allowed-cidrs="0.0.0.0/0" ``` To only allow specific IPs, you can give a list of IPs with subnet mask: ```bash nctl update postgres {NAME} --allowed-cidrs="203.0.113.1/32,..." ``` You can also allow your own IP using the following parameter: ```bash nctl update postgres {NAME} --allowed-cidrs="$(curl -s ipinfo.io/ip)/32" ``` For more information on IP filtering and using an SSH key, see the [Database documentation](/user-guide/configuring-your-database.md). ## Configure Your PHP Application Add the database server as a service reference to your application: ```bash nctl update app {APP_NAME} \ --service db=postgres/{NAME} ``` If the application is already running, create a new release so the injected service variables become available: ```bash nctl update app {APP_NAME} --retry-release ``` The following environment variables have been injected into your application: | Variable | Description | | :--- | :--- | | `NINE_PG__FQDN` | Hostname. Uses private networking DNS when private networking is configured; otherwise the public hostname. | | `NINE_PG__PORT` | Port `(always 5432)`. | | `NINE_PG__USER` | Username. | | `NINE_PG__PASSWORD` | Password. | | `NINE_PG__CA_CERT` | CA certificate. Only injected when a CA certificate is present. | | `NINE_PG__DSN` | Full PostgreSQL connection URI (`postgres://user:pass@host:port/dbname`). | Where `` is the reference name you assigned in `--service =..`, uppercased with non-alphanumeric characters replaced by `_`. For example, the previously used reference name `db` becomes `DB`. See the [technical reference](https://docs.nine.ch/docs/deplo-io/configuration/deploio-connecting-to-services) for more info on service references. ## Create the database To create a database on the database server, start an interactive shell in your web application with: ```bash nctl exec app {APP_NAME} ``` In that shell, run the following command to create the database: ```bash bin/console doctrine:database:create ``` You can verify that this database was created by logging into the database server using `psql -U dbadmin -h {FQDN} -d postgres` and then running the command `\l` to list the databases on the server. > **Alternative:** If you do not use Doctrine or otherwise want to do something differently, make sure that your IP is allowed to connect > to the database server and then use a Postgres client to create the database. E.g. with the Postgres CLI: > > Connect to the database server: > > ```bash > psql -U dbadmin -h {FQDN} -d postgres > ``` > > You will be prompted to enter the password. Once connected, you can create the database: > > ```sql > CREATE DATABASE my_database; > ``` > > Verify the database was created: > > ```sql > SELECT datname FROM pg_database; > ``` ### Troubleshooting If you encounter any issues when **connecting to the database**, check that your IP address was correctly added to the allowed CIDRs. You can do this by running: ```bash nctl get postgres {NAME} -o yaml ``` and then search for the `allowedCIDRs` field. To add your current IP address, you could use the following command: ```bash nctl update postgres {NAME} --allowed-cidrs "$(curl -s ipinfo.io/ip)/32" ``` Also, ensure that your current **client version is compatible with the database version**. You can find the currently used version in the YAML output of `nctl get` by searching for the `version` field. \== MySQL #### Economy Create a MySQL database: ```bash nctl create mysqldatabase {NAME} ``` Add the database as a service reference to your application: ```bash nctl update app {APP_NAME} \ --service db=mysqldatabase/{NAME} ``` If the application is already running, create a new release so the injected service variables become available: ```bash nctl update app {APP_NAME} --retry-release ``` The following environment variables have been injected into your application: | Variable | Description | | :--- | :--- | | `NINE_MYSQLDB__FQDN` | Hostname. Uses private networking DNS when private networking is configured; otherwise the public hostname. | | `NINE_MYSQLDB__PORT` | Port `(always 3306)`. | | `NINE_MYSQLDB__USER` | Username (same as the database name assigned at creation). | | `NINE_MYSQLDB__PASSWORD` | Password. | | `NINE_MYSQLDB__CA_CERT` | CA certificate. Only injected when a CA certificate is present. | Where `` is the reference name you assigned in `--service =..`, uppercased with non-alphanumeric characters replaced by `_`. For example, the previously used reference name `db` becomes `DB`. See the [technical reference](https://docs.nine.ch/docs/deplo-io/configuration/deploio-connecting-to-services) for more info on service references. #### Business To create a MySQL database server for your PHP application, you can use the `nctl create` command like this: ```bash nctl create mysql {NAME} \ --character-set-collation=utf8mb4_unicode_ci \ --machine-type=nine-db-s \ --location=nine-cz42 ``` Further details on the flags can be found in the manual by running `nctl create mysql --help`. Note that currently, only MySQL 8 databases are supported. You can now access the server using the **fully-qualified domain name (FQDN)** and the generated user and password. Retrieve this information by running: ```bash $ nctl get mysql {NAME} PROJECT NAME FQDN LOCATION MACHINE TYPE my-project {NAME} {NAME}.1234567.mysql.nineapis.ch nine-cz41 nine-db-s $ nctl get mysql {NAME} --print-user dbadmin $ nctl get mysql {NAME} --print-password ...password... ``` For more setup commands, visit the [Nine MySQL documentation](https://docs.nine.ch/docs/on-demand-databases/on-demand-databases-mysql/). ## Access to the server By default, your database server is only accessible from applications running in Deploio. If you want to access the database server from your local machine or some other location, you need to configure network exceptions with the `--allowed-cidrs` option. To allow all IPs, you would use the following parameter: ```bash nctl update mysql {NAME} --allowed-cidrs="0.0.0.0/0" ``` To only allow specific IPs, you can give a list of IPs with subnet mask: ```bash nctl update mysql {NAME} --allowed-cidrs="203.0.113.1/32,..." ``` You can also allow your own IP using the following parameter: ```bash nctl update mysql {NAME} --allowed-cidrs="$(curl -s ipinfo.io/ip)/32" ``` For more information on IP filtering and using an SSH key, see the [Database documentation](/user-guide/configuring-your-database.md). ## Configure Your PHP Application Add the database server as a service reference to your application: ```bash nctl update app {APP_NAME} \ --service db=mysql/{NAME} ``` If the application is already running, create a new release so the injected service variables become available: ```bash nctl update app {APP_NAME} --retry-release ``` The following environment variables have been injected into your application: | Variable | Description | | :--- | :--- | | `NINE_MYSQL__FQDN` | Hostname. Uses private networking DNS when private networking is configured; otherwise the public hostname. | | `NINE_MYSQL__PORT` | Port `(always 3306)`. | | `NINE_MYSQL__USER` | Username (same as the database name assigned at creation). | | `NINE_MYSQL__PASSWORD` | Password. | | `NINE_MYSQL__CA_CERT` | CA certificate. Only injected when a CA certificate is present. | Where `` is the reference name you assigned in `--service =..`, uppercased with non-alphanumeric characters replaced by `_`. For example, the previously used reference name `db` becomes `DB`. See the [technical reference](https://docs.nine.ch/docs/deplo-io/configuration/deploio-connecting-to-services) for more info on service references. ## Create the database To create a database on the database server, start an interactive shell in your web application with: ```bash nctl exec app {APP_NAME} ``` In that shell, run the following command to create the database: ```bash bin/console doctrine:database:create ``` You can verify that this database was created by logging into the database server from your local machine (using `mysql -h {FQDN} -u dbadmin -p --ssl-mode=REQUIRED`) and then running the command `SHOW DATABASES;` to list the databases on the server. > **Alternative:** If you do not use Doctrine or otherwise want to do something differently, make sure that your IP is allowed to connect > to the database server and then use a MySQL client from **your machine** to create the database. E.g. with the MySQL CLI: > > Connect to the database server: > > ```bash > mysql -h {FQDN} -u dbadmin -p --ssl-mode=REQUIRED > ``` > > You will be prompted to enter the password. Once connected, you can create the database: > > ```sql > CREATE DATABASE my_database; > ``` > > To check that the database was created, you can run the query `SHOW DATABASES;`. > > **Warning:** Currently, Deploio supports **MySQL version 8**. If you have MySQL version 9 installed on your local machine, > you probably lack the `mysql_native_password` plugin as it has been removed in MySQL 9. > Hence, you would need to install an older version of the client > (e.g. `brew install mysql-client@8.4` and then `/opt/homebrew/opt/mysql-client@8.4/bin/mysql -h ...` on macOS using Homebrew). ### Troubleshooting If you encounter any issues when **connecting to the database**, check that your IP address was correctly added to the allowed CIDRs. You can do this by running: ```bash nctl get mysql {NAME} -o yaml ``` and then search for the `allowedCIDRs` field. To add your current IP address, you could use the following command: ```bash nctl update mysql {NAME} --allowed-cidrs "$(curl -s ipinfo.io/ip)/32" ``` Also, ensure that your current **client version is compatible with the database version**. You can find the currently used version in the YAML output of `nctl get` by searching for the `version` field. ::: ## Using the Database in your PHP Application When using Symfony, you must update your configuration to check for the specific environment variables Deploio injects based on your database type and tier. Since the reference name `db` becomes `DB`, you configure your application as follows. Update your doctrine config file based on your database type and tier (`config/packages/doctrine.yaml`): For PostgreSQL Business: ```php file="config/packages/doctrine.yaml" doctrine: dbal: url: '%env(resolve:NINE_PG_DB_DSN)%' ``` For PostgreSQL Economy: ```php file="config/packages/doctrine.yaml" doctrine: dbal: url: '%env(resolve:NINE_PGDB_DB_DSN)%' ``` For MySQL Business: ```php file="config/packages/doctrine.yaml" doctrine: dbal: driver: 'pdo_mysql' host: '%env(resolve:NINE_MYSQL_DB_FQDN)%' port: '%env(resolve:NINE_MYSQL_DB_PORT)%' user: '%env(resolve:NINE_MYSQL_DB_USER)%' password: '%env(resolve:NINE_MYSQL_DB_PASSWORD)%' dbname: 'my_database' charset: utf8mb4 options: !php/const:PDO::MYSQL_ATTR_SSL_CA: '%env(resolve:NINE_MYSQL_DB_CA_CERT)%' ``` For MySQL Economy: ```php file="config/packages/doctrine.yaml" doctrine: dbal: driver: 'pdo_mysql' host: '%env(resolve:NINE_MYSQLDB_DB_FQDN)%' port: '%env(resolve:NINE_MYSQLDB_DB_PORT)%' user: '%env(resolve:NINE_MYSQLDB_DB_USER)%' password: '%env(resolve:NINE_MYSQLDB_DB_PASSWORD)%' dbname: 'my_database' charset: utf8mb4 ``` If you use Doctrine DBAL without the Symfony configuration, you no longer need a parser for MySQL, as Deploio provides the exact fields you need natively. You can dynamically detect which database and tier is attached: ```php $pgDsn]; } else { // Detect MySQL (Business or Economy) $connectionParams = [ 'dbname' => 'my_database', // Update this with your actual database name 'user' => getenv('NINE_MYSQL_DB_USER') ?: getenv('NINE_MYSQLDB_DB_USER'), 'password' => getenv('NINE_MYSQL_DB_PASSWORD') ?: getenv('NINE_MYSQLDB_DB_PASSWORD'), 'host' => getenv('NINE_MYSQL_DB_FQDN') ?: getenv('NINE_MYSQLDB_DB_FQDN'), 'port' => getenv('NINE_MYSQL_DB_PORT') ?: getenv('NINE_MYSQLDB_DB_PORT'), 'driver' => 'pdo_mysql', ]; } $conn = DriverManager::getConnection($connectionParams); ``` ::: Tip Because Deploio now automatically injects granular variables (like NINE\_MYSQL\_DB\_USER and NINE\_MYSQL\_DB\_PASSWORD), you no longer need complex JSON-encoding workarounds to parse connection strings into separate fields for MySQL databases. You can pass these environment variables directly into native PHP PDO or mysqli instances if you choose not to use Doctrine. ::: ### Run Migrations Doctrine provides the [doctrine/migrations](https://www.doctrine-project.org/projects/doctrine-migrations/en/3.9/index.html) package to manage database schema migrations. To run the migrations, specify a deploy job in your [`deploio.yaml`](/user-guide/configuring-your-application.md#_3-deploio-yaml) or run the migrations manually: ```bash nctl exec app {APP_NAME} bin/console doctrine:migrations:migrate ``` If you did not get any errors during the migration, you should now have a healthy connection to your database and be able to interact with it through your Symfony application. ## Next Steps Do you need a Redis-compatible **key value store** for your application? Proceed to the next step. --- --- url: 'https://guides.deplo.io/ruby/database.md' description: >- Instructions for creating and configuring PostgreSQL or MySQL databases for Rails applications including connection setup, migrations, and troubleshooting. --- # Create a database for your Rails application ::: info In this guide, we will show you how to create a database for your Ruby on Rails application using Deploio. You can see more information on databases [here](/user-guide/configuring-your-database.md). Should you wish to migrate an already existing database from elsewhere, you can view this section in the documentation [here](/user-guide/migrating-from-other-platforms.md). ::: ## Choose a tier Deploio offers two database tiers. See the [database guide](/user-guide/configuring-your-database.md) for full details. | | Economy | Business | |----------------------------|-----------------------------------------|--------------------------------| | **Best for** | Development, testing, low-traffic sites | Production, high-traffic sites | | **Databases per instance** | 1 | Multiple | | **Storage** | Up to 10 GB | 20 GB+ (auto-expanding) | | **Resources** | Shared (multi-tenant) | Dedicated instance | ## Create the database ::: tip To ensure the database resource gets allocated to the correct project, you should switch to the correct project context: ```bash nctl auth set-project my-project ``` Alternatively, you can specify the project name with the `-p, --project` flag in the following commands. ::: :::tabs key:db \== PostgreSQL #### Economy Create a PostgreSQL database: ```bash nctl create postgresdatabase {NAME} ``` Add the database as a service reference to your application: ```bash nctl update app {APP_NAME} \ --service db=postgresdatabase/{NAME} ``` If the application is already running, create a new release so the injected service variables become available: ```bash nctl update app {APP_NAME} --retry-release ``` The following environment variables have been injected into your application: | Variable | Description | | :--- | :--- | | `NINE_PGDB__FQDN` | Hostname. Uses private networking DNS when private networking is configured; otherwise the public hostname. | | `NINE_PGDB__PORT` | Port `(always 5432)`. | | `NINE_PGDB__USER` | Database name (same as the name assigned at creation). | | `NINE_PGDB__PASSWORD` | Password. | | `NINE_PGDB__CA_CERT` | CA certificate. Only injected when a CA certificate is present. | | `NINE_PGDB__DSN` | Full PostgreSQL connection URI `(postgres://user:pass@host:port/dbname)`. | Where `` is the reference name you assigned in `--service =..`, uppercased with non-alphanumeric characters replaced by `_`. For example, the previously used reference name `db` becomes `DB`. See the [technical reference](https://docs.nine.ch/docs/deplo-io/configuration/deploio-connecting-to-services) for more info on service references. #### Business To create a Postgres database server for your Ruby application, you can use the `nctl create` command like this: ```bash nctl create postgres {NAME} \ --postgres-version=17 \ --machine-type=nine-db-xs \ --location=nine-cz42 ``` Retrieve the connection details: ```bash $ nctl get postgres {NAME} PROJECT NAME FQDN LOCATION MACHINE TYPE my-project {NAME} {NAME}.postgres.nineapis.ch nine-cz41 nine-db-xs $ nctl get postgres {NAME} --print-user dbadmin $ nctl get postgres {NAME} --print-password ...password... ``` ## Access to the server By default, your database server is only accessible from applications running in Deploio. If you want to access the database server from your local machine or some other location, you need to configure network exceptions with the `--allowed-cidrs` option. To allow all IPs, you would use the following parameter: ```bash nctl update postgres {NAME} --allowed-cidrs="0.0.0.0/0" ``` To only allow specific IPs, you can give a list of IPs with subnet mask: ```bash nctl update postgres {NAME} --allowed-cidrs="203.0.113.1/32,..." ``` You can also allow your own IP using the following parameter: ```bash nctl update postgres {NAME} --allowed-cidrs="$(curl -s ipinfo.io/ip)/32" ``` For more information on IP filtering and using an SSH key, see the [Database documentation](/user-guide/configuring-your-database.md). ## Configure Your Rails Application Add the database server as a service reference to your application: ```bash nctl update app {APP_NAME} \ --service db=postgres/{NAME} ``` If the application is already running, create a new release so the injected service variables become available: ```bash nctl update app {APP_NAME} --retry-release ``` The following environment variables have been injected into your application: | Variable | Description | | :--- | :--- | | `NINE_PG__FQDN` | Hostname. Uses private networking DNS when private networking is configured; otherwise the public hostname. | | `NINE_PG__PORT` | Port `(always 5432)`. | | `NINE_PG__USER` | Username. | | `NINE_PG__PASSWORD` | Password. | | `NINE_PG__CA_CERT` | CA certificate. Only injected when a CA certificate is present. | | `NINE_PG__DSN` | Full PostgreSQL connection URI (`postgres://user:pass@host:port/dbname`). | Where `` is the reference name you assigned in `--service =..`, uppercased with non-alphanumeric characters replaced by `_`. For example, the previously used reference name `db` becomes `DB`. See the [technical reference](https://docs.nine.ch/docs/deplo-io/configuration/deploio-connecting-to-services) for more info on service references. ## Create the database To create a database on the database server, start an interactive shell in your web application with: ```bash nctl exec app {APP_NAME} ``` In that shell, run the following command to create the database: ```bash createdb -U dbadmin -h {FQDN} my-database ``` 1. You will be asked for the password. You can verify the database was created by connecting with `psql -U dbadmin -h {FQDN} -d postgres` and running the following SQL query: ```sql SELECT datname FROM pg_database; ``` #### Troubleshooting If you encounter any issues when **connecting to a Business database**, check that your IP address was correctly added to the allowed CIDRs: ```bash nctl get postgres {NAME} -o yaml ``` Search for the `allowedCIDRs` field. To add your current IP address: ```bash nctl update postgres {NAME} --allowed-cidrs "$(curl -s ipinfo.io/ip)/32" ``` Also, ensure that your current **client version is compatible with the database version**. You can find the currently used version in the YAML output of `nctl get` by searching for the `version` field. \== MySQL #### Economy Create a MySQL database: ```bash nctl create mysqldatabase {NAME} ``` Add the database as a service reference to your application: ```bash nctl update app {APP_NAME} \ --service db=mysqldatabase/{NAME} ``` If the application is already running, create a new release so the injected service variables become available: ```bash nctl update app {APP_NAME} --retry-release ``` The following environment variables have been injected into your application: | Variable | Description | | :--- | :--- | | `NINE_MYSQLDB__FQDN` | Hostname. Uses private networking DNS when private networking is configured; otherwise the public hostname. | | `NINE_MYSQLDB__PORT` | Port `(always 3306)`. | | `NINE_MYSQLDB__USER` | Username (same as the database name assigned at creation). | | `NINE_MYSQLDB__PASSWORD` | Password. | | `NINE_MYSQLDB__CA_CERT` | CA certificate. Only injected when a CA certificate is present. | Where `` is the reference name you assigned in `--service =..`, uppercased with non-alphanumeric characters replaced by `_`. For example, the previously used reference name `db` becomes `DB`. See the [technical reference](https://docs.nine.ch/docs/deplo-io/configuration/deploio-connecting-to-services) for more info on service references. #### Business To create a MySQL database server for your Ruby application, you can use the `nctl create` command like this: ```bash nctl create mysql {NAME} \ --character-set-collation=utf8mb4_unicode_ci \ --machine-type=nine-db-xs \ --location=nine-cz42 ``` Further details on the flags can be found by running `nctl create mysql --help`. Note that currently, only MySQL 8 databases are supported. Retrieve the connection details: ```bash $ nctl get mysql {NAME} PROJECT NAME FQDN LOCATION MACHINE TYPE my-project {NAME} {NAME}.1234567.mysql.nineapis.ch nine-cz41 nine-db-xs $ nctl get mysql {NAME} --print-user dbadmin $ nctl get mysql {NAME} --print-password ...password... ``` ## Access to the server By default, your database server is only accessible from applications running in Deploio. If you want to access the database server from your local machine or some other location, you need to configure network exceptions with the `--allowed-cidrs` option. To allow all IPs, you would use the following parameter: ```bash nctl update mysql {NAME} --allowed-cidrs="0.0.0.0/0" ``` To only allow specific IPs, you can give a list of IPs with subnet mask: ```bash nctl update mysql {NAME} --allowed-cidrs="203.0.113.1/32,..." ``` You can also allow your own IP using the following parameter: ```bash nctl update mysql {NAME} --allowed-cidrs="$(curl -s ipinfo.io/ip)/32" ``` For more information on IP filtering and using an SSH key, see the [Database documentation](/user-guide/configuring-your-database.md). ## Configure your Rails application Add the database as a service reference to your application: ```bash nctl update app {APP_NAME} \ --service db=mysql/{NAME} ``` If the application is already running, create a new release so the injected service variables become available: ```bash nctl update app {APP_NAME} --retry-release ``` The following environment variables have been injected into your application: | Variable | Description | | :--- | :--- | | `NINE_MYSQL__FQDN` | Hostname. Uses private networking DNS when private networking is configured; otherwise the public hostname. | | `NINE_MYSQL__PORT` | Port `(always 3306)`. | | `NINE_MYSQL__USER` | Username (same as the database name assigned at creation). | | `NINE_MYSQL__PASSWORD` | Password. | | `NINE_MYSQL__CA_CERT` | CA certificate. Only injected when a CA certificate is present. | Where `` is the reference name you assigned in `--service =..`, uppercased with non-alphanumeric characters replaced by `_`. For example, the previously used reference name `db` becomes `DB`. See the [technical reference](https://docs.nine.ch/docs/deplo-io/configuration/deploio-connecting-to-services) for more info on service references. ## Create the database To create a database on the database server, make sure that your local machine's IP address is allowed to connect to the database server. Then, use a MySQL client directly from your **local machine** to create the database. ```bash mysql -h {FQDN} -u dbadmin -p --ssl-mode=REQUIRED ``` You will be prompted to enter your database admin password. > **Warning:** Deploio supports **MySQL version 8**. If you have MySQL 9 installed locally, you > may lack the `mysql_native_password` plugin. Install an older client instead > (e.g. `brew install mysql-client@8.4`). Once connected, create the database: ```sql CREATE DATABASE my_database; ``` Verify with `SHOW DATABASES;`. #### Troubleshooting If you encounter any issues when **connecting to a Business database**, check that your IP address was correctly added to the allowed CIDRs: ```bash nctl get mysql {NAME} -o yaml ``` Search for the `allowedCIDRs` field. To add your current IP address: ```bash nctl update mysql {NAME} --allowed-cidrs "$(curl -s ipinfo.io/ip)/32" ``` Also, ensure that your current **client version is compatible with the database version**. You can find the currently used version in the YAML output of `nctl get` by searching for the `version` field. ::: ## Further Steps ##### Check Database Configuration You need to adjust the `database.yml` file in your Rails application to ensure that it is using the correct database. If this file does not exist in your `config/` directory (common in modern Rails 7+ apps), create it manually. Here is an example configuration: ```yaml default: &default adapter: postgresql # Change to 'mysql2' if using MySQL encoding: unicode pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> development: <<: *default database: project_name_development test: <<: *default database: project_name_test production: <<: *default # For PostgreSQL Tiers (Business or Economy) url: "<%= ENV['NINE_PG_DB_DSN'] || ENV['NINE_PGDB_DB_DSN'] %>" # For MySQL Tiers (Business or Economy) # Un-comment the lines below if you are using MySQL instead of PostgreSQL: # host: "<%= ENV['NINE_MYSQL_DB_FQDN'] || ENV['NINE_MYSQLDB_DB_FQDN'] %>" # port: "<%= ENV['NINE_MYSQL_DB_PORT'] || ENV['NINE_MYSQLDB_DB_PORT'] %>" # username: "<%= ENV['NINE_MYSQL_DB_USER'] || ENV['NINE_MYSQLDB_DB_USER'] %>" # password: "<%= ENV['NINE_MYSQL_DB_PASSWORD'] || ENV['NINE_MYSQLDB_DB_PASSWORD'] %>" # database: my_database ``` To verify that Rails can connect to the database, open a shell in your app and run a quick query via the Rails runner: ```bash nctl exec app {APP_NAME} -- bundle exec rails runner "puts ActiveRecord::Base.connection.execute('SELECT 1').first" ``` If the connection is working, this prints `{"?column?"=>"1"}` (PostgreSQL) or `{"1"=>1}` (MySQL). If it fails, double-check your custom NINE\_ environment variables and database.yml settings. ##### Run Migrations You can now run the database migrations to create the tables in the database. This can be done through the [`.deploio.yaml`](/user-guide/configuring-your-application.md#_3-deploio-yaml) file by specifying a deploy job: ```yaml deployJob: name: db-migrations command: bundle exec rails db:migrate retries: 0 timeout: 5m ``` or by manually running the migrations: ```bash nctl exec app {APP_NAME} bundle exec rails db:migrate ``` If you did not get any errors during the migration, you should now have a healthy connection to your database and be able to interact with it through your Rails application. ## Next Steps Do you need a Redis-compatible **key value store** for your application (e.g. for running Sidekiq)? Proceed to the next step. --- --- url: 'https://guides.deplo.io/php/key-value-storage.md' description: >- Guide for setting up Redis-compatible key-value stores for PHP applications supporting caching and Symfony configurations with TLS connections. --- # Create a Key Value Store for your PHP application ::: info Should you require workers or caching, you can use our Redis-compatible key-value store (KVS). You can see the different sizes available and pricing [here](/user-guide/other-dependencies.md#key-value-store). ::: ## Create the Key Value Store ::: tip Before you create resources, ensure that the project you want to create the resources in is selected by running `nctl auth set-project {project_name}`. ::: Create the key value store with the `create kvs` command: ```bash nctl create kvs {KVS_NAME} ``` This creates a key-value store owned by the currently active project. The key-value store supports the Redis 7 API. ::: info Due to [license changes](https://redis.io/blog/what-redis-license-change-means-for-our-managed-service-providers/) and the associated uncertainty about the future development of Redis, Deploio will switch away from Redis to a compatible alternative as a replacement soon. ::: ## Bind the Key Value Store to your Application Add the key-value store as a service reference to your application. By using `redis=` as the alias, Deploio will automatically inject the granular `NINE_KVS_REDIS_*` environment variables into your application. ```bash nctl update app {APP_NAME} \ --service redis=kvs/{KVS_NAME} ``` If the application is already running, create a new release so the injected service variables become available: ```bash nctl update app {APP_NAME} --retry-release ``` See the [technical reference](https://docs.nine.ch/docs/deplo-io/configuration/deploio-connecting-to-services) for more info on service references, injected environment variables, and how to remove a service reference. ## Using the Key Value Store in your PHP Application When using Symfony, you must update your configuration to construct the connection string using the granular environment variables Deploio injects. Since the reference name used in the binding step was `redis`, the placeholder name becomes `REDIS`, meaning your injected variables are prefixed with `NINE_KVS_REDIS_`. Update your cache config file `(config/packages/cache.yaml)`: ```yaml file="config/packages/cache.yaml" framework: cache: default_redis_provider: 'redis://%env(NINE_KVS_REDIS_USER)%:%env(NINE_KVS_REDIS_PASSWORD)%@%env(NINE_KVS_REDIS_FQDN)%:%env(NINE_KVS_REDIS_PORT)%' ``` If your Redis setup does not require an explicit username configuration, you can alternatively format the provider string like this: ```yaml file="config/packages/cache.yaml" framework: cache: default_redis_provider: 'redis://:%env(NINE_KVS_REDIS_PASSWORD)%@%env(NINE_KVS_REDIS_FQDN)%:%env(NINE_KVS_REDIS_PORT)%' ``` If you use a native PHP Redis client (such as PHPRedis) instead of the framework configuration, you no longer need complex JSON-encoding workarounds or URL parsers to handle your connection parameters. You can initialize your connection parameters directly using the individual environment variables: ```php connect($host, $port); if ($password) { if ($user) { // For Redis setups leveraging modern ACL usernames $redis->auth(['user' => $user, 'pass' => $password]); } else { // Classic password-only authentication $redis->auth($password); } } ``` ::: tip Because Deploio automatically handles the heavy lifting by injecting granular environment variables (like `NINE_KVS_REDIS_FQDN` and `NINE_KVS_REDIS_PASSWORD`), you do not need to manage a monolithic `REDIS_URL` string or run custom parsing scripts to separate your connection components. ::: ## Next Steps Do you need **object storage** for your application? Proceed to the next step. --- --- url: 'https://guides.deplo.io/ruby/key-value-storage.md' description: >- Guide for setting up Redis-compatible key-value stores for Rails applications to support caching and background job systems like Sidekiq. --- # Create a Key Value Store for your Ruby on Rails application ::: info Are you using Sidekiq? Or ActionCable with Redis? Deploio offers a managed Redis-compatible key-value store. This guide describes how you can set it up. You can see the different tiers and pricing [here](/user-guide/other-dependencies.md#key-value-store). ::: ## Create the Key Value Store ::: tip Before you create resources, ensure that the project you want to create the resources in is selected by running `nctl auth set-project {project_name}`. ::: Create the key value store with the `create kvs` command: ```bash nctl create kvs {KVS_NAME} ``` This creates a key-value store owned by the currently active project. The key-value store supports the Redis 7 API. ::: info Due to [license changes](https://redis.io/blog/what-redis-license-change-means-for-our-managed-service-providers/) and the associated uncertainty about the future development of Redis, Deploio will switch away from Redis to a compatible alternative as a replacement soon. ::: ## Bind the Key Value Store to your Application Add the key-value store as a service reference to your application. By using `redis=` as the alias, Deploio will automatically inject the granular `NINE_KVS_REDIS_*` environment variables into your application. ```bash nctl update app {APP_NAME} \ --service redis=kvs/{KVS_NAME} ``` If the application is already running, create a new release so the injected service variables become available: ```bash nctl update app {APP_NAME} --retry-release ``` See the [technical reference](https://docs.nine.ch/docs/deplo-io/configuration/deploio-connecting-to-services) for more info on service references, injected environment variables, and how to remove a service reference. ## Configure Rails Add the `redis` gem to your `Gemfile` if it's not already present: ```ruby gem "redis" ``` Deploio KVS instances use self-signed TLS certificates. You need to disable certificate verification in every Redis connection by passing `ssl_params`. Since the reference name used in the binding step was `redis`, your injected variables are prefixed with `NINE_KVS_REDIS_`. ### Sidekiq If you're using Sidekiq, construct the Redis connection URL using your injected variables. Create or update `config/initializers/sidekiq.rb`: ```ruby redis_url = "redis://#{ENV['NINE_KVS_REDIS_USER']}:#{ENV['NINE_KVS_REDIS_PASSWORD']}@#{ENV['NINE_KVS_REDIS_FQDN']}:#{ENV['NINE_KVS_REDIS_PORT']}" Sidekiq.configure_server do |config| config.redis = { url: redis_url, ssl_params: { verify_mode: OpenSSL::SSL::VERIFY_NONE } } end Sidekiq.configure_client do |config| config.redis = { url: redis_url, ssl_params: { verify_mode: OpenSSL::SSL::VERIFY_NONE } } end ``` Then add a worker for Sidekiq as described in the [Background Jobs guide](./background-jobs.md): ```bash nctl update app {APP_NAME} \ --worker-job-command="bundle exec sidekiq -C config/sidekiq.yml" \ --worker-job-name "sidekiq" \ --worker-job-size micro ``` ### ActionCable To use ActionCable with Redis, construct the URL string directly in your `config/cable.yml`: ```yaml production: adapter: redis url: redis://<%= ENV["NINE_KVS_REDIS_USER"] %>:<%= ENV["NINE_KVS_REDIS_PASSWORD"] %>@<%= ENV["NINE_KVS_REDIS_FQDN"] %>:<%= ENV["NINE_KVS_REDIS_PORT"] %> ssl_params: verify_mode: <%= OpenSSL::SSL::VERIFY_NONE %> ``` ### Cache Store To use Redis as the Rails cache store, add the following connection configuration to `config/environments/production.rb`: ```ruby redis_url = "redis://#{ENV['NINE_KVS_REDIS_USER']}:#{ENV['NINE_KVS_REDIS_PASSWORD']}@#{ENV['NINE_KVS_REDIS_FQDN']}:#{ENV['NINE_KVS_REDIS_PORT']}" config.cache_store = :redis_cache_store, { url: redis_url, ssl_params: { verify_mode: OpenSSL::SSL::VERIFY_NONE } } ``` ## Verify the Connection You can verify that your application can reach the key-value store by running a quick check via `nctl exec`: ```bash nctl exec app {APP_NAME} -- bundle exec rails runner \ "r = Redis.new(host: ENV['NINE_KVS_REDIS_FQDN'], port: ENV['NINE_KVS_REDIS_PORT'], username: ENV['NINE_KVS_REDIS_USER'], password: ENV['NINE_KVS_REDIS_PASSWORD'], ssl_params: { verify_mode: OpenSSL::SSL::VERIFY_NONE }); r.set('ping', 'pong'); puts r.get('ping')" ``` If the connection is working, this prints `pong`. You can read more about KVS configuration in the [technical reference](https://docs.nine.ch/docs/on-demand-databases/on-demand-key-value-store/). ## Next Steps Do you need **object storage** for your application? Proceed to the next step. --- --- url: 'https://guides.deplo.io/ruby/quick-start.md' description: >- Step-by-step guide for deploying Ruby on Rails applications on Deploio using Heroku buildpacks with nctl CLI and Git repositories. --- # Create a Rails Application ::: info This guide covers how to deploy a Ruby on Rails application with Deploio. It assumes you have a basic understanding of Ruby on Rails and Git. ::: ## Prerequisites * This quick start guide assumes you have **installed `nctl` on your laptop**. If not, please go through the instructions [here](/user-guide/getting-started.md#installing-nctl). * You should also have an **organization and project created**, where you will create the application. If you haven't done this yet, please follow the instructions [here](/user-guide/getting-started.md#setting-up-your-first-project). * A locally running version of Ruby, Rubygems, Bundler, and Rails ## Setup Rails app In case you don't have a Rails application yet, you can create one using the Rails CLI. We recommend following the [official Rails guide](https://guides.rubyonrails.org/getting_started.html#creating-your-first-rails-app) to create a new Rails application. We also have a basic Rails app in our [examples repository](https://github.com/ninech/deploio-examples/tree/main/heroku-stack#ruby-on-rails), which you can also choose as a starting point. ::: warning Right now, Deploio does not support SQLite databases. You will need to use PostgreSQL or MySQL if you wish to persist data. This can be configured by passing the `--database` flag to the `rails new` command with either `postgresql` or `mysql`. ::: Add the `x86_64-linux` and `ruby` platforms to your Gemfile, to ensure that the correct gems are installed on the platform: ```shell cd myapp bundle lock --add-platform x86_64-linux --add-platform ruby ``` ## Setup Git Deploio requires your application to be available online in a Git repository, so that it can be cloned and deployed by the platform. You can use any Git repository hosting service, such as GitHub, GitLab, or Bitbucket. We describe the process of setting up a Git repository [here](/user-guide/code-repository-setup.md). For demonstration purposes, we will use our sample Rails application hosted on GitHub. ::: info This example presumes that you are **using a public repository**. Should you need to set up access to a private repository, you will need to create an SSH key for security. See more details [here](/user-guide/code-repository-setup.md). ::: ## Create Deploio app ::: info The following app creation command requires the [Rails CLI](https://guides.rubyonrails.org/command_line.html) to generate `SECRET_KEY_BASE`. If you don't have it, any long random string will do (127+ chars), e.g. `openssl rand -hex 64` or `head -c 64 /dev/urandom | xxd -p -c 0`. ::: Replace `MY_RAILS_APP_NAME` with your chosen app name and run: ::: warning The app name you choose **cannot be changed later**. ::: ```bash nctl create app MY_RAILS_APP_NAME \ --git-url=https://github.com/ninech/deploio-examples \ --git-sub-path=heroku-stack/ruby/rails-basic \ --buildpack-stack=heroku \ --env="SECRET_KEY_BASE=$(rails secret)" ``` You can pass multiple environment variables by separating them with `;`. Run `nctl create app --help` to see all available options. When you create an application, the Git repository is cloned and Deploio will attempt to detect the application type and select the appropriate buildpack. In this case, the Paketo Ruby buildpack will be used. The buildpack will then attempt to detect the desired ruby version from the `Gemfile.lock` in the app source. ::: info If your application requires **Node.js** either for the build or runtime, a `package.json` file must be present at the root of the repository for the Node.js runtime to be installed. ::: ## Next Steps The app should be running by now. You can check the status as follows. ```bash nctl get app MY_RAILS_APP_NAME --project=MY_PROJECT_NAME ``` The output includes a **HOSTS** column with your app's default URL (ending in `.deploio.app`). You can verify the app is responding by opening that URL in your browser or by running: ```bash curl -i https://MY_RAILS_APP_NAME-xxxxxx.deploio.app ``` If your application requires a database, it will likely fail at this point because the database connection is not yet configured. You can check your app configuration with: ```bash nctl get app MY_RAILS_APP_NAME --project=MY_PROJECT_NAME -o yaml ``` You can also open an interactive shell to inspect or debug: ```bash nctl exec app MY_RAILS_APP_NAME --project=MY_PROJECT_NAME ``` The next step is to set up a [**database**](/ruby/database.md) for your application. --- --- url: 'https://guides.deplo.io/php/object-storage.md' description: >- Guide for configuring S3-compatible object storage for PHP applications using Flysystem for file uploads and persistent storage needs. --- # Create an Object Storage for your PHP application ::: info Should you require a file upload or a writable storage, you can use our S3-compatible object storage. You can use Amazon S3 together with Deploio as you would with any other hosting provider. If you wish to have a persistent, S3 compatible storage that also runs on Nine's infrastructure and is directly connected to Deploio, you can use our S3-compatible object storage. You can see the pricing [here](https://docs.nine.ch/docs/object-storage/manage-buckets-and-users#pricing). ::: ## Setup Object Storage Currently, there's no dedicated command to create an object storage instance using `nctl`. However, you can create an object storage via the [Cockpit UI](https://cockpit.nine.ch/en/object_storage/storage/buckets/new). Select the desired project in the dropdown and specify the location, which ideally is `nine-es34`, the same location as Deploio applications. For more information about our data center locations, see our [locations documentation](https://docs.nine.ch/docs/managed-kubernetes/nke/nine-kubernetes-engine#locations). ::: info Even though the `nctl` CLI does not have a dedicated command for object storage, you can still create it using the `nctl apply` command: Using a resource definition like the example below, you can create an object storage instance using the `nctl apply -f bucket.yaml` command and delete it using `nctl delete -f bucket.yaml`, respectively. ```yaml title="bucket.yaml" apiVersion: storage.nine.ch/v1alpha1 kind: Bucket metadata: name: example namespace: spec: forProvider: location: nine-es34 storageTier: standard ``` ## Retrieve Object Storage Information After creating the object storage, you can view the access information by navigating to the details page of the newly created **bucket**. ![Object Storage Panel](/img/object_storage_panel.png) However, to interact with the created object storage, you need to create a **bucket user**. You can do this by clicking "Add User" on the bucket page and creating the user. The user needs to reside in the same location as the bucket. After creating the user, you can retrieve the access key and secret key by clicking on "Show" in the "Credentials" row. ![Bucket User Panel](/img/bucket_user_panel.png) ![Bucket User Credentials](/img/bucket_user_credentials.png) You will need the access key and the secret key, the user name is not used on the client. ## Configure your PHP Application S3 cannot be mounted as a local filesystem, so you need a client to let PHP interact with S3. In the example application, we use [Flysystem](https://flysystem.thephpleague.com/docs/) with the [S3 plugin](https://flysystem.thephpleague.com/docs/adapter/aws-s3-v3/) (which itself uses the AWS SDK for PHP). The `league/flysystem-bundle` does not support specifying the connection as DSN, therefore we added `webalternatif/flysystem-dsn-bundle`. The configuration looks like this (note that you can define multiple adapters if you want to connect to multiple buckets. For each bucket, you would use a different DSN.) ```yaml title="config/flysystem.yml" webf_flysystem_dsn: adapters: persistent_adapter: '%env(STORAGE_URL)%' flysystem: storages: persistent.storage: adapter: webf_flysystem_dsn.adapter.persistent_adapter ``` You can set the environment variables using the information you retrieved from the Cockpit: ```bash nctl update app {application_name} --env="STORAGE_URL=s3://{ACCESS KEY}:{SECRET KEY}@es34.objects.nineapis.ch?region=us-east-1&bucket={NAME}" ``` ::: info For S3, a `region` must be specified. Deploio uses the S3 default value of `us-east-1`, even though the servers are in Switzerland, operated by Nine. See the [FAQ](../user-guide/faq.md#why-do-i-have-to-set-the-s3-region-to-us-east-1) for details. ::: ## Next Steps Do you need **background jobs** for your application? Proceed to the next step. --- --- url: 'https://guides.deplo.io/static-pages/static-site-generators.md' description: >- Comprehensive guide for deploying static site generators like VitePress, Docusaurus, Gatsby, and Astro on Deploio with build script configuration and output directory setup. --- # Deploying Static Site Generators Static site generators (SSGs) like VitePress, Docusaurus, Gatsby, and Astro use Node.js during the build process to generate static HTML, CSS, and JavaScript files. ::: info This guide covers deploying SSGs that **require a build step**. If you have a simple static site with just HTML/CSS/JS files, see the [Quick Start Guide for Static Sites](/static-pages/quick-start.md). ::: ## How It Works Deploio uses buildpacks to automatically detect and build your application: 1. **Node.js buildpack** detects your `package.json` 2. Runs `npm install` (or `yarn install`) 3. Runs `npm run build` to generate static files 4. **Nginx buildpack** serves the generated files ## Required Configuration ### 1. Build Script in package.json Your `package.json` **must** include a `build` script: ```json { "scripts": { "build": "vitepress build docs" // your framework's build command } } ``` ::: warning Without a `build` script, Deploio will not detect your application as a Node.js project. ::: ### 2. Build Output Directory Set the `BP_STATIC_WEBROOT` build environment variable to tell Deploio where your generated files are located. **Common frameworks and their output directories:** | Framework | Default Output | `BP_STATIC_WEBROOT` | |-----------|---------------|---------------------| | VitePress | `docs/.vitepress/dist` | `docs/.vitepress/dist` | | Docusaurus | `build` | `build` | | Gatsby | `public` | `public` | | Astro | `dist` | `dist` | | Next.js (static) | `out` | `out` | ::: tip Check your framework's documentation to confirm the output directory. ::: ## Framework-Specific Examples ### VitePress **package.json:** ```json { "scripts": { "build": "vitepress build docs" } } ``` **Build Environment Variable:** ``` BP_STATIC_WEBROOT=docs/.vitepress/dist ``` ### Docusaurus **package.json:** ```json { "scripts": { "build": "docusaurus build" } } ``` **Build Environment Variable:** ``` BP_STATIC_WEBROOT=build ``` ::: tip Docusaurus uses `build` as the default, which matches Deploio's default `BP_STATIC_WEBROOT`. ::: ### Gatsby **package.json:** ```json { "scripts": { "build": "gatsby build" } } ``` **Build Environment Variable:** ``` BP_STATIC_WEBROOT=public ``` ### Astro **package.json:** ```json { "scripts": { "build": "astro build" } } ``` **Build Environment Variable:** ``` BP_STATIC_WEBROOT=dist ``` ## Common Issues ### Build Script Not Found **Problem:** Site deploys but build doesn't run. **Solution:** Add a `build` script to your `package.json`. ### 404 After Deployment **Problem:** Site deploys successfully but shows 404 errors. **Causes:** * `BP_STATIC_WEBROOT` is pointing to the wrong directory * `BP_STATIC_WEBROOT` is not set **Solution:** Verify your framework's output directory and set `BP_STATIC_WEBROOT` correctly. ### Node Version If your build requires a specific Node.js version, specify it in `package.json`: ```json { "engines": { "node": "20.x" } } ``` Or create a `.nvmrc` file: ``` 20 ``` ## Best Practices ### Don't Commit Build Artifacts Add these to your `.gitignore`: ```gitignore node_modules/ dist/ build/ .cache/ out/ docs/.vitepress/dist/ docs/.vitepress/cache/ ``` ### Build-Time Environment Variables For configuration that needs to be embedded in your static files (API endpoints, feature flags), use build environment variables. ::: warning Build environment variables are embedded in the generated static files. **Never** include secrets or sensitive data. ::: ### Lock Files Always commit your `package-lock.json` or `yarn.lock` file for reproducible builds. ## Related Guides * [Getting Started](/user-guide/getting-started.md) - Initial setup and account creation * [Code Repository Setup](/user-guide/code-repository-setup.md) - Connecting your Git repository * [CI/CD Integration](/user-guide/ci-cd-integration.md) - Automated deployments --- --- url: 'https://guides.deplo.io/user-guide/faq.md' --- # FAQ Answers to questions that come up regularly — especially about design decisions that may seem surprising at first. ## How Swiss is Deploio really? Your applications, databases, and storage run in Nine's data centers in Switzerland. There are currently two caveats you should be aware of: * **The control cluster runs on Google Cloud Platform.** The Deploio API (`nineapis.ch`) points to GCP because the k8s control cluster runs there for historical reasons. This dependency has no influence on the data integrity of your applications: workloads and their data stay in Switzerland, only the management plane runs on GCP. Nine is aware of this limitation and is working on migrating this system to its own infrastructure. * **24/7 support involves a Canadian subsidiary.** Nine provides around-the-clock support through a subsidiary in Canada. This takes advantage of the timezone shift. The details are listed in [Appendix 3 of the Data Processing Agreement](https://docs.nine.ch/docs/legal-documents/data-processing-agreement/#appendix-3). Opt-out is possible for other Nine products but not for Deploio yet. ## Why do I have to set the S3 region to `us-east-1`? The S3 protocol requires a region for request signing, so S3 clients refuse to work without one. Deploio's object storage accepts the S3 default value `us-east-1` — it is purely a protocol-level label and says nothing about where your data lives. The buckets are hosted in Switzerland, operated by Nine. See the [Active Storage](../ruby/active-storage.md) (Rails) and [Object storage](../php/object-storage.md) (PHP) guides for configuration examples. ## What do the data center region names mean? The data center locations (e.g. named `nine-cz42` or `nine-es34`) are all in Switzerland. * `cz` stands for ["ColoZüri"](https://www.peeringdb.com/fac/336) in Zürich Altstetten. * `es` stands for "e-shelter", the old name of [NTT Zürich 1](https://www.peeringdb.com/fac/1185) in Rümlang. ## How much Heroku is in Deploio? Hopefully a lot! Heroku is one of the giants on whose shoulders we stand. You can configure Deploio with [Heroku buildpacks](https://docs.nine.ch/docs/deplo-io/configuration/buildpack-stacks#heroku-stack-default). Buildpacks are piece of software which describes how your app should be deployed. The Heroku buildpacks are the most compatible and best tested on the market and they are [open sourced under BSD license](https://github.com/heroku/buildpacks). This means your code is built the same way as it would on Heroku, but all running **under control of Nine**. **Options:** You can use [Paketo buildpacks](https://docs.nine.ch/docs/deplo-io/configuration/buildpack-stacks/#paketo-stack) or build with a [Dockerfile](https://docs.nine.ch/docs/deplo-io/dockerfile-build). ## Why is my app down during maintenance windows? Nine [defines maintenance windows](https://docs.nine.ch/docs/general/weekly-maintenance-window) to introduce security patches and upgrades. You can prevent these downtimes by configuring at least 2 replicas for your app. ## Why can apps not be renamed? This is a restriction of the underlying k8s infrastructure. It's a good old Swiss compromise, a tradeoff between using autogenerated cryptic handles and human-readable identifiers. But you can label an app with a display name to help you identify it. ## How to deploy private Git submodules or repository-dependencies? The credentials which work for your main git repo must be setup by you to also work for your sub-repo or submodule. **Github** does not allow to use the same deploy key in different repositories, so you must use a [classic PAT](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#personal-access-tokens-classic) or refer to a [Docker build](../docker/quick-start.md#build-arguments) using a custom secret in your the build environment. --- --- url: 'https://guides.deplo.io/user-guide/getting-started.md' description: >- Complete guide for getting started with Deploio including nctl CLI installation, account setup, project creation, and best practices to avoid common pitfalls. --- # Getting Started This guide helps you get up and running with **Deploio**, from installing the CLI (`nctl`) to creating your first project. You'll also find resources, best practices, and common pitfalls to avoid. ## Installing nctl **`nctl`** is the command-line interface used to interact with Deploio and the underlying Nine Kubernetes Engine (NKE). You can use it to manage projects, trigger deployments, view logs, and more. 📄 **Read the full nctl API docs [here](https://docs.nine.ch/api/)** ### Step-by-step setup 1. Download and install `nctl`. Various methods of installation are detailed on the [GitHub page](https://github.com/ninech/nctl#installation). 2. Log in to the API (provided you have an account) using: ```bash nctl auth login ``` 3. Check you are authenticated and have access to the API: ```bash nctl auth whoami ``` 4. View your available projects: ```bash nctl get all ``` ## Creating an account ### Setting up access within an organization Accounts in Deploio are tied to your **Customer Account** (or `organization`). When logging in via nctl, your identity and permissions reflect what’s configured in the Cockpit for your organization. If you have Administrator access on the organization, you can manage users and access for the organization directly in the [Cockpit](https://cockpit.nine.ch/en/customer/contacts). If the organization already exists and you need a new user account, you need to: * Ask your admin to invite you to the correct organization * Log in using your credentials provided * Authenticate `nctl` using `nctl auth login` (see [here](/introduction/how-deploio-works.md#nctl)) Once you are set up, you can check your available organizations once logged in on the CLI by running `nctl auth whoami`. ### Setting up a new user or organization If you do not have an organization set up and wish to do so, you should contact Nine directly. There is a contact form and details at [Deplo.io](https://deplo.io/). Should you wish to create an individual user, you can do so on the [Cockpit registration page](https://cockpit.nine.ch/de/signup?). ## Setting up your first project In Deploio, the structure follows a strict hierarchy: ```mermaid flowchart TD Org[Organization] --> ProjectA[Project A] Org --> ProjectB[Project B] ProjectA --> App1A[Application: Web App] ProjectB --> App1B[Application: Main] ProjectB --> App2B[Application: Develop] ``` A created `Organization` is the top-level entity, which can contain multiple projects. A `Project` is the logical container to group applications within. Each project can have multiple applications. This structure allows for better organization and management of resources. An `Application` is the actual deployment unit. It can be a web application, a microservice, or any other deployable unit. Each application is associated with a specific project and inherits the default configuration from the project unless specified otherwise. You can see an explanation of the configuration levels [here](https://docs.nine.ch/docs/deplo-io/configuration/deploio-configuration-layers/). ## Useful resources ### Blogs There are a number of blogs and other resources available that can provide more information and use cases for Deploio. Please see a list below: * [Nine blog](https://nine.ch/de/blog/) * [Deploio success story](https://deplo.io/en/success_story) * [Case studies](https://nine.ch/en/products/deploio/#casestudies) ### Quick start guides We provide quick-start guides for various programming languages and frameworks. Head over to the [landing page](https://guides.deplo.io/) to see the full list. ### Videos Under [this YouTube playlist](https://youtube.com/playlist?list=PLlOLIwramZLMHkeEYWAt82VwuQdB0b6P-) you can find a list of demos and behind-the-scenes insights into Deploio. ## Avoid common pitfalls * If you are **using Node in your application**, you need: * A `package.json` in the root of the project * The following environment variable during the build process: `BP_INCLUDE_NODEJS_RUNTIME="true"` * Always **check your current session** and access with: `nctl auth whoami` * Always make sure you **set the project** in which you wish to make changes with: `nctl auth set-project my-project` * Otherwise, you can specifically **set the project as a flag**. For example: `nctl get configs --project=org-my-project ` * Projects are **prefixed with your organization name**. For example `my-project` within `org` can be referred to as `org-my-project`. ## Best Practices for Beginners [//]: # "- Suggested defaults for deployment configurations with explanation" [//]: # "- Security guidelines for managing secrets and roles" * Store secrets securely using environment variables managed via Cockpit or nctl. * Regularly review and update your configurations to ensure they meet the latest security and performance standards. * Use staging environments to test your applications before deploying to production. * Monitor your applications using the available [monitoring tools](/user-guide/monitoring-and-logs.md). --- --- url: 'https://guides.deplo.io/introduction/how-deploio-works.md' description: >- Explains the repo-build-release process, workflow, and key concepts including projects, deployments, Cockpit, and nctl CLI in Deploio's Kubernetes infrastructure. --- # How Deploio Works In this section, you'll learn how Deploio works, from the repo, build, release process to the workflow and glossary of key terms. ## Repo, Build, Release Process All you require for deploying an application with Deploio is: * a git repository with the application codebase * a laptop or PC for installing `nctl` and deploying the application 💻 * a domain to point to your application 🌐 ##### Repo Tell Deploio where your source code lives — whether it's GitHub, GitLab, or Bitbucket, or even a private git server. You can specify a branch or tag to deploy from, and Deploio will handle fetching the code securely via OAuth or SSH authentication. Check out [Code Repository Setup](/user-guide/code-repository-setup.md) for more details. ##### Build Deploio automatically builds your application using the [Heroku Buildpack](https://elements.heroku.com/buildpacks) or your own Dockerfile. It automatically detects the appropriate language runtime, installs dependencies, and compiles your code into a production-ready image. Build logs are streamed in real-time and stored for traceability. ##### Release After a successful build, your application is released. The release includes the build artifact, configuration settings, and environment variables. Releases are immutable and versioned. Deploio also manages secrets and sensitive data securely, differentiating between build and release environment variables. While release ENV variables are exposed to the running application, build ENV variables are only available during the build process and are not included in the final release. ##### Run Deploio runs your application on a managed Kubernetes cluster, powered by **Nine Kubernetes Engine** (NKE), located in Switzerland. Deployments are automatically rolled out using zero-downtime strategies such as rolling updates and health checks. Applications run in isolated pods, scheduled across nodes provisioned via configurable node pools and machine types. This ensures high availability and scalability. Apps are exposed to the internet via k8s ingress controllers. Other services are not. All communication is secured with TLS (also internally). While Deploio runs on a scalable Kubernetes infrastructure, your apps don’t autoscale by default. Most apps can live comfortably with vertical scaling — predictable, easy to manage, and fully under your control via code, CI/CD, or manually in the Cockpit. You probably don’t need horizontal scaling, but if you do, we’ve got you. Because we run on real Kubernetes, and we know how to scale things properly. Do you? For more details on the infrastructure used to run your app, view the Nine Kubernetes Engine documentation [here](https://docs.nine.ch/docs/managed-kubernetes/nke/nine-kubernetes-engine/). ## Workflow ##### Code Management Deploio connects to your Git provider (e.g., GitHub, GitLab, Bitbucket) via SSH. It fetches code from your repo and triggers deployments on push or manual triggers. Unlike Heroku, Deploio does not host your Git repo — it uses your existing setup. See the [Code Repository Setup](/user-guide/code-repository-setup.md) page for more detail. ##### Build Automation Either use the provided official Heroku Cloud Native Buildpacks for languages like Node.js, Ruby, Python, and Go — or define a custom Dockerfile. Builds are cached to speed things up. Configuration isn’t limited to environment variables: Deploio uses a **hierarchical system** that lets you define defaults at the company or project level easily, and override them per app — either in the code or directly in the Cockpit. ##### Deployment Deployments are rolled out through Kubernetes using rolling updates and readiness checks to ensure zero downtime. Each deployment references a specific container image and configuration version. Deploy jobs can also be configured to execute before a new release is deployed. The rollout of the release will only continue if the deploy job finished successfully. This can be defined in the `.deploio.yaml`. See more information [here](/user-guide/configuring-your-application.md#_3-deploio-yaml). ```mermaid flowchart TD %% Top-level vertical flow A([Push code to Git repository]) --> B B --> C C --> D D --> E %% Build steps subgraph buildGraph [ ] direction LR B([Pull latest code from repo]) C([Build container image using buildpacks or Dockerfile]) D([Create versioned release with image & app config]) end %% NKE cluster (vertical) subgraph NKE Cluster direction TB E([Deploy to Kubernetes]) F[Pods scheduled across nodes] G[Ingress with TLS and load balancing] end G --> H([Application is available securely]) ``` ## Glossary of Key Terms ##### Project A project represents a workspace that contains one or more applications and related services such as databases, Redis instances and object storage. It is a logical grouping of applications and services that share the same codebase, configuration, and deployment settings and billing. Projects are isolated from each other, allowing for better organisation and management of resources. It is typical that a Project will have an Application running for each environment. But be aware: staging apps can access production services unless access controls are explicitly defined - similar to Heroku. ##### Deployment The act of **bringing your code to the web**: build and ship a specific state of your code, config, and environment — made live under a domain. Fully reproducible. Fully auditable. ##### Cockpit The Deploio web interface, providing a visual dashboard to manage your projects, view logs, monitor deployments, and configure settings. It’s your control center. This works hand in hand with nctl, the command-line tool for advanced management. ##### nctl The official Deploio CLI tool for developers. It can be used for the whole process; from creating a project to deploying an application. It provides a command-line interface for managing your projects, deployments, and environments. You can use it to trigger builds, manage environments, inspect logs, and control deployments right from your terminal. ##### UI The Deploio web interface, providing a visual dashboard to manage your resources, view logs, and monitor deployments. You can access it over at [cockpit.nine.ch](https://cockpit.nine.ch/). Learn more about the process on [docs.nine.ch](https://docs.nine.ch). --- --- url: 'https://guides.deplo.io/markdown-examples.md' --- # Markdown Extension Examples This page demonstrates some of the built-in markdown extensions provided by VitePress. ## Syntax Highlighting VitePress provides Syntax Highlighting powered by [Shiki](https://github.com/shikijs/shiki), with additional features like line-highlighting: **Input** ````md ```js{4} export default { data () { return { msg: 'Highlighted!' } } } ``` ```` **Output** ```js{4} export default { data () { return { msg: 'Highlighted!' } } } ``` ## Custom Containers **Input** ```md ::: info This is an info box. ::: ::: tip This is a tip. ::: ::: warning This is a warning. ::: ::: danger This is a dangerous warning. ::: ::: details This is a details block. ::: ``` **Output** ::: info This is an info box. ::: ::: tip This is a tip. ::: ::: warning This is a warning. ::: ::: danger This is a dangerous warning. ::: ::: details This is a details block. ::: ## More Check out the documentation for the [full list of markdown extensions](https://vitepress.dev/guide/markdown). --- --- url: 'https://guides.deplo.io/user-guide/migrating-from-other-platforms.md' description: >- Migration guide for moving applications to Deploio from Heroku and other platforms including database exports, environment variables, DNS updates, and CI/CD adaptation. --- # Migrating from Other Platforms With Deploio, it is extremely easy to migrate an application, and all resources, from other providers. In this section we will provide information on how to migrate environment variables, databases, as well as how to adapt the DNS records and CI workflows. Most examples will focus on migrating from Heroku, however this can be adapted should you be migrating from another provider. ## Retrieving and restoring databases When migrating your application to Deploio, you'll need to migrate your database as well, if you have one. The process generally involves three main steps: 1. Create a new database instance on Deploio 2. Export your data from the source platform 3. Import the data into your Deploio database ### 1. Create a Database on Deploio First, you'll need to create a new database instance on Deploio. You can do this using the `nctl` command line tool (or in the Cockpit). For more details on database configuration options when creating a database, see the [Configuring your Database page](/user-guide/configuring-your-database.md). ### 2. Export Data from Source Platform The method for exporting your database will depend on your source platform. Here are some common approaches: #### PostgreSQL Databases For PostgreSQL databases, you can use `pg_dump` to create a backup: ```bash pg_dump -h {SOURCE_HOST} -U {USERNAME} -d {DATABASE_NAME} -f backup.dump ``` #### MySQL Databases For MySQL databases, you can use `mysqldump`: ```bash mysqldump -h {SOURCE_HOST} -u {USERNAME} -p {DATABASE_NAME} > backup.sql ``` #### Platform-Specific Examples Some platforms provide their own tools for database exports: **Heroku Example:** ```bash # Capture a backup heroku pg:backups:capture -a {APP_NAME} # Download the backup heroku pg:backups:download -a {APP_NAME} ``` **AWS RDS Example:** ```bash # Using AWS CLI to create a snapshot aws rds create-db-snapshot \ --db-instance-identifier {INSTANCE_ID} \ --db-snapshot-identifier {SNAPSHOT_NAME} ``` ### 3. Import Data to Deploio Once you have your database backup file (e.g. `backup.dump` or `backup.sql`), you can import it into your Deploio database: #### PostgreSQL ```bash pg_restore \ -U dbadmin \ -h {DEPLOIO_FQDN} \ -d {DATABASE_NAME} \ -c -v backup.dump \ --no-owner --no-acl ``` ::: info The `--no-owner` and `--no-acl` flags are important when restoring to Deploio: * `--no-owner`: Ensures all objects are owned by the user performing the restore (dbadmin) rather than the original owner * `--no-acl`: Prevents the restoration of access control lists (ACLs) from the source database, which might cause issues with access to the database. ::: #### MySQL ```bash mysql -h {DEPLOIO_FQDN} -u dbadmin -p {DATABASE_NAME} < backup.sql ``` ### 4. Update Application Configuration After the migration is complete, update your application's database connection string: ```bash nctl update app {APP_NAME} \ --env="DATABASE_URL=$(nctl get postgres {DATABASE_NAME} --print-connection-string)/{DATABASE_NAME}" ``` This can also be done in the Cockpit. ### Best Practices * Always create a backup of your source database before starting the migration * Test the migration process in a staging environment first * Consider the size of your database and plan for appropriate downtime / maintenance window * Verify data integrity after the migration * Update any database-specific configurations in your application ### Troubleshooting If you encounter issues during the migration: * Check the database connection settings * Verify that your IP address is allowed in the `allowed-cidrs` * Ensure you have the correct database version * Check the database logs for any errors * Verify that your backup file is not corrupted For more detailed information about database configuration and management on Deploio, see the [database configuration guide](/user-guide/configuring-your-database.md). ## Retrieving environment variables Below is an example of a shell script that you can use for retrieving environment variables. Depending on the platform you are migrating from, and whether they have a comprehensive CLI infrastructure, this could be adapted for your case. In the below example, you would need to replace the `heroku_project` variable with your project name. The output will be a list of environment variables from the project which can then be passed when creating the application using the `nctl` command line. The [Heroku cli](https://devcenter.heroku.com/articles/heroku-cli) and [`jq` command line utility](https://jqlang.github.io/jq/) have to be installed. `env-migration.sh`: ```shell set -e # Function to convert JSON to --env='KEY=VALUE;KEY=VALUE;...' format convert_json_to_env() { local json_input="$1" # Process the JSON input and format it accordingly echo "--env='"$(echo "$json_input" | jq -r 'to_entries | map("\(.key)=\(.value|tostring)") | join(";")')"'" } # Fetching JSON input from Heroku config heroku_project="heroku_project" json_input=$(heroku config -a $heroku_project -j) echo "$json_input" # Check if json_input is empty if [ -z "$json_input" ]; then echo "Error: Could not fetch Heroku config or config is empty." exit 1 fi # Converting JSON to --env='KEY=VALUE;KEY=VALUE;...' format env_arguments=$(convert_json_to_env "$json_input") # Print the result echo "$env_arguments" ``` The script can also be adapted as required, for example we could use the below **grep** to avoid setting environment variables that start with `HEROKU`. ``` jq 'to_entries | map(select(.key | startswith("HEROKU") | not)) | map("\(.key)=\(.value)") | join(";") ``` Once you are happy with the script, you can then simply run `bash env-migration.sh` and the output will look something like this: ``` { "ADMIN_EMAIL": "admin@admin.ch", "ADMIN_PASSWORD": "password" } --env='ADMIN_EMAIL=admin@damin.ch;ADMIN_PASSWORD=password' ``` The second output can now be passed when creating the application. We can just keep these at hand for when we create the application, or, if the application is already created, we can update using the below command: ``` nctl update app gifcoins --env='ADMIN_EMAIL=admin@damin.ch;ADMIN_PASSWORD=password' ``` **Disclaimer:** Please be aware that this is just an example of how to automate retrieving the environment variables. The user should make sure that they understand the script, which environment variables they require, and thoroughly check the output. ## Updating DNS records Given that we now have a new URL for the application, we will need to update the DNS records to point to the new application running on Deploio. ##### An example using Cloudflare Below we go through an example of adapting this where we use Cloudflare to manage our DNS records. [//]: # "TODO: show an example with some images" ##### Considerations It may be that you need to disable the "proxy mode"... [//]: # "TODO: show an example with some images" ## Adapting deployment workflows for Deploio Currently, when we link the GitHub repository and target revision for the application, the application will automatically re-deploy on branch changes. If this is sufficient, the application can remain with this setup pointing to a static branch. ##### Integrating to the CI On the other hand, should you wish to integrate the deployment process to the CI, allowing the test suite to run before deployment, we can adapt the process to do so. [//]: # "TODO: add from migration guide" ## How to guides Please see a list below of "how to" guides for migrating to Deploio: --- --- url: 'https://guides.deplo.io/user-guide/monitoring-and-logs.md' --- # Monitoring and Logs ## Logs Your application's stdout and stderr output is captured by Deploio and can be accessed either in the Cockpit or with `nctl`. ### Viewing Application Logs To view the latest logs of your application: ```bash nctl logs app {application_name} ``` By default, this shows the last 50 lines. You can adjust this with `--lines`: ```bash nctl logs app {application_name} --lines 200 ``` To follow live logs, use `--follow`: ```bash nctl logs app {application_name} --follow ``` ::: info To have a more structured and highlighted output, you can easily use third-party tools like, for example, [`tailspin`](https://github.com/bensadeh/tailspin): ```bash nctl logs app {application_name} --output json | tspin ``` ::: ### Filtering Logs Deploio captures logs from different sources. You can filter by type (e.g. deploy or worker jobs) using the `--type` flag: ```bash # App logs nctl logs app {application_name} --type app # Build logs nctl logs app {application_name} --type build # Deploy job logs nctl logs app {application_name} --type deploy_job # Worker job logs nctl logs app {application_name} --type worker_job # Scheduled job logs nctl logs app {application_name} --type scheduled_job ``` ### Time-Based Filtering You can look back a specific duration or query an absolute time range: ```bash # Logs from the last 2 hours nctl logs app {application_name} --since 2h # Logs in a specific time window (RFC3339 format) nctl logs app {application_name} \ --from 2025-01-15T08:00:00+01:00 \ --to 2025-01-15T09:00:00+01:00 ``` ### Structured output For structured log processing, you can output logs as JSON instead of plain text: ```bash nctl logs app {application_name} --output json ``` ### Retention Deploio retains logs for up to 30 days. ## Performance Metrics We currently provide **CPU** and **memory usage** metrics for your application replicas. The following sections explain how you can access these metrics. In case you need more detailed metrics, we offer you the option to set up your own Grafana dashboard. See the [Metrics in your own Grafana Dashboard](#metrics-in-your-own-grafana-dashboard) section for details. ### Resource Stats To see the current CPU and memory usage of your application replicas, you can use: ```bash nctl get app {application_name} -o stats ``` This shows per-replica metrics: | Column | Description | |--------|-------------| | REPLICA | Name of the app replica | | STATUS | Current status of the replica | | CPU | CPU usage in millicores (1000m = 1 full core) | | CPU% | CPU usage relative to app size (can exceed 100% due to bursting) | | MEMORY | Memory usage in MiB | | MEMORY% | Memory usage relative to app size (can exceed 100% due to bursting) | | RESTARTS | Number of times the replica has restarted | | LASTEXITCODE | Exit code from the last restart (useful for diagnosing crash loops) | ### Releases and Builds To see what's currently live and the deployment history: ```bash # List all releases nctl get releases -a {application_name} # List all builds nctl get builds -a {application_name} ``` To find out which git revision is currently deployed: ```bash nctl get app {application_name} --output yaml | grep revision ``` ### Metrics in Cockpit The Cockpit web interface provides a Metrics tab for each application, displaying memory and CPU usage over time. ### Metrics of running replica Next to using `nctl` or the Cockpit, you can also just connect to the running replica directly and use tool like `free` to check the memory usage e.g.: ```bash # Init shell session nctl exec app {application_name} bash # Print memory usage free -m ``` ### Metrics in your own Grafana Dashboard Grafana offers you the possibility to set up your own dashboard to monitor your applications. In order to provision a Grafana instance, head over to the Nine Cockpit and navigate to "On-Demand Services" and click on "New Service". This will navigate you to a form where you can select Grafana. Once the Grafana instance is up and running, you can import our [pre-made Deploio dashboard](https://docs.nine.ch/docs/deplo-io/observing-your-app#dashboard), which you can then still customize to your needs. --- --- url: 'https://guides.deplo.io/user-guide/network-and-deployment.md' description: >- Guide for setting up custom domains with DNS records (CNAME and TXT) and configuring automatic SSL certificates via Let's Encrypt on Deploio. --- # Network & Deployment Once your application is built and running, the next step is making it accessible to the world. This section focuses on the external-facing aspects - domains, security, static IPs and deployment configuration - that allow users to connect to your app. In this section, you will learn how to configure how your app is seen and secured on the web. ## Setting up a custom domain If you are using a service that manages DNS and SSL certificates for you (e.g., Cloudflare), you need to provide the service with the details of your Deploio application. The service will then route traffic to your application. ##### Check the app is running Deploio provides a "first host" or default URL for your application. This URL can be used initially to check if your application is running. You can find this by running the following command and looking under the HOSTS column: ```bash nctl auth set-project {PROJECT_NAME} nctl get app {APP_NAME} ``` ::: info This will list all hosts for the application. If you have added multiple hosts, the default host will be the URL that ends with "deploio.app". ::: Alternatively, you can find the default host on the Application page in the Cockpit under the **Hosts** tab. It is the host with the status **"Default Host"**. ##### Create the domain This will differ depending on the service you are using. However, the steps should be similar. For example, if you are using Cloudflare, you can add a new domain by going to the Cloudflare dashboard and clicking on the **"Add a domain"** button. Here, you can enter an existing domain or register a new one. You will need to purchase the domain from a registrar for the setup to work. Follow the instructions provided to create the domain. Once this is complete, you will need to set up the DNS records for the domain. ##### Create the DNS records Your service should provide an overview of the DNS records for your domain and allow you to add A, AAAA, CNAME, TXT, etc. records. For Deploio, you will need to add both a CNAME and TXT record. The **CNAME** record will require a "Name" field, which should match the domain or subdomain you want to use for your application. The target will be the **default URL** for your application, as discussed [above](#check-the-app-is-running). If your DNS provider offers proxy settings (like cyon.ch or other providers), we recommend initially setting it to direct DNS routing without proxying to ensure there are no connection issues. You can enable proxying features later if needed, but disabling them initially will help troubleshoot any connection problems. The **TXT** record will also require a "Name" field. The content for the TXT record can be found on the Application page in the Cockpit, under the **Hosts** tab. Copy the **TXT Record Content** and paste it into the TXT record, including the quotation marks. For example: ```txt "deploio-site-verification=application-name-abcdef123456" ``` ::: info SSL and Let's Encrypt Once your DNS records are properly configured and verified, Deploio automatically provisions SSL certificates for your domains through Let's Encrypt. The TXT record not only verifies your domain ownership for Deploio but also helps with the domain validation process that Let's Encrypt requires. This automated process ensures your application is secured with HTTPS without any manual certificate management. For more details about SSL certificates, see the [Securing your application with SSL](#securing-your-application-with-ssl) section below. ::: ##### Add the host to the application Once you have added the DNS records, you can add the host to the application. This can be done via `nctl update app {APP_NAME} --hosts="..."`. It is important to note that this will replace any existing hosts for the application configuration. Therefore, we would recommend checking the existing configuration, adding any hosts as desired, and updating the application. For example, first get the host configuration for the application: ```bash nctl get app {APP_NAME} --project {PROJECT_NAME} ``` The output will look something like this: ```plaintext PROJECT NAME REPLICAS WORKERJOBS HOSTS UNVERIFIEDHOSTS {PROJECT_NAME} {APP_NAME} 1 0 abc.com,xyz.com ``` You can then update the application with the new host configuration: ```bash nctl update app {APP_NAME} --hosts="abc.com,xyz.com,newhost.com" --project {PROJECT_NAME} ``` Alternatively, you can visit the Application page in the **Cockpit** and click on the **Edit** button. Under **Hosts**, you can add as many hosts as you want. These should match the domain and/or subdomain you have configured. You can then click on the **Update Application** button to save the changes. ##### Check the domain is working Once you have added the DNS records, you can check if the domain is working by returning to the **Hosts** tab. Deploio will automatically check the status of the host, and if it is working, it will change to **"Verified"**. Please note that this might take a few minutes. Once the host is verified, you can visit the domain and check everything is working. ## Securing your application with SSL ##### Let's Encrypt Deploio automatically handles SSL certificates using Let's Encrypt, so you don't need to manage them yourself. To use a custom domain, simply point it to the default URL provided by Deploio. This URL is already secured with SSL, ensuring your application is secure without additional configuration. You don't need to configure Nginx or any other web server manually — Deploio takes care of the server configuration for you. Whenever you add a custom hostname, a corresponding Let's Encrypt SSL certificate will be created. You can see the status of these certificates via `nctl get app {APP_NAME} -o yaml`: ```yaml kind: Application ... status: atProvider: ... defaultHostsCertificateStatus: Issued customHostsCertificateStatus: Pending ``` As we are using the Let's Encrypt HTTP-01 challenge type, the certificate will only be successfully issued once all of your custom hostnames point to the Deploio infrastructure. We use an optimized DNS resolving path to quickly react to DNS changes, but it might still take a few minutes before the certificate can be issued. Please also keep in mind that Let's Encrypt favors IPv6 DNS entries over IPv4 ones. If you have DNS AAAA records for your custom hostnames, make sure to delete them when migrating to Deploio (as Deploio does not currently support IPv6). ## Static egress IP We provide the option to configure a static egress IP address. This ensures that outgoing traffic from your Deploio application always comes from the same IP address. The same IP address will also be used for worker and scheduled jobs. ::: info Why? For example if your app talks to an on-premises backend which is guarded by a firewall allowing only traffic from specific IP addresses. ::: In order to configure a static egress IP, follow these instructions: 1. Replace the placeholders in the following YAML configuration and save it as `deploio-static-egress.yaml` ```yaml apiVersion: networking.nine.ch/v1alpha1 kind: StaticEgress metadata: name: my-deploio-static-egress namespace: spec: forProvider: disabled: false target: group: apps.nine.ch kind: Application name: ``` 2. Apply the configuration ```bash nctl apply -f deploio-static-egress.yaml ``` Once the configuration is applied, all egress traffic will come from the same IP address. You can find the IP address by running the following command: ```bash kubectl --context nineapis.ch get staticegress my-deploio-static-egress \ -n -o yaml ``` See the [Nine Technical Reference](https://docs.nine.ch/docs/managed-kubernetes/nke/static-egress-nke/?client=kubectl#details) for more details about the static egress feature. --- --- url: 'https://guides.deplo.io/user-guide/other-dependencies.md' description: >- Guide for setting up Redis-compatible key-value stores, object storage, and persistent volumes as dependencies for Deploio applications. --- # Other Dependencies This guide covers how to set up a Redis-compatible key-value store and S3-compatible object storage. These dependencies can be used for caching, task queues or to store static files and assets. ## Key-Value Store #### Redis for caching or task queues Should you require workers or caching, you can use Redis as a key-value store. You can see the different sizes available and pricing [here](https://docs.nine.ch/docs/on-demand-databases/on-demand-key-value-store/). [//]: # "TODO: should we move all that across to here? I'm confused as to whether those docs will remain..." Due to [licence changes](https://redis.io/blog/what-redis-license-change-means-for-our-managed-service-providers/) and the associated uncertainty about the future development of Redis, we have decided to use a Redis-compatible alternative as a replacement in the near future. #### Creating the Key-Value Store Firstly, we create the key-value store by running the `create kvs` command: ``` nctl create kvs {application_name} --project {project_name} ``` This creates the Redis instance with name `{application_name}` within the project space. We now need to retrieve the information for this created instance, and set the environment variables using this information. ::: info `kvs` is short for `keyvaluestore`. `nctl` also works if you use the long name `nctl create keyvaluestore my-kvs ...`. ::: Firstly, we can get the **FQDN**, and check the other details, by running: ``` nctl get kvs {application_name} ``` We will also need to get the **password** for the access by running: ``` nctl get kvs {application_name} --print-token ``` From this we can construct and set the `REDIS_URL` and `REDISCLI_AUTH` environment variables as follows: ``` nctl update app {application_name} --env='REDIS_URL=rediss://:{PASSWORD}@{FQDN};REDISCLI_AUTH={PASSWORD}' ``` Note that we are using `rediss` as TLS is enabled. ## Object Storage **Deploio doesn't give you a disk to store files permanently.** It's because real hard disk storage is difficult to scale horizontally. So the [12factor](https://12factor.net/backing-services) industry best practice has been for quite some time to use cloud storage, most famously Amazon S3. We call this "object storage". ::: info If you absolutely need a real persistent and backed-up disk, consider using a [Nine CloudVM](https://nine.ch/products/root-cloud-server/) or [bring your own server hardware](https://nine.ch/de/produkte/colocation/) instead. ::: #### Setup bucket and user Following command creates a bucket named `{bucket_name}` in the project space: ``` nctl create bucket {bucket_name} --project {project_name} --location nine-es34 ``` Nine has multiple [datacenter locations](https://docs.nine.ch/docs/managed-kubernetes/nke/nine-kubernetes-engine#locations). `nine-es34` is the default for Deploio. In order to access the bucket, we need to create a user with access to it. ``` nctl create bucketuser --location=nine-es34 {bucketuser_name} ``` Afterwards you can retrieve the access key and secret key for this user by running ``` nctl get bucketuser {bucketuser_name} --print-credentials ``` #### Connecting The created bucket is S3-compatible, meaning you can use any S3 client to connect your application to it, such as the AWS CLI or the `boto3` Python library. In addition, if you want to connect manually to the bucket, we've documented a list of possible tools and their required configuration in this [guide](https://docs.nine.ch/docs/object-storage/object-storage-client-tools). #### Encryption Object storage files are encrypted at rest on disk. --- --- url: 'https://guides.deplo.io/introduction/our-stack.md' description: >- Overview of Deploio's technology stack including Nutanix infrastructure, Kubernetes orchestration, Swiss hosting (AS29691), Docker containers, and Heroku buildpacks. --- # Our Stack ## The Human Stack Deploio is born from a partnership of two established Swiss technology companies: ### Nine (Founded 1999) * Decades of Swiss hosting expertise * Operates Swiss-based datacenters * Deep infrastructure and cloud engineering experience ### Renuo (Founded 2011) * Platform-as-a-Service specialists * Years of Heroku power-user experience (plus testing a number of alternatives) * Expert application deployment knowledge ##### Together, they bring Swiss quality, reliability, and technical excellence to Deploio. ## The Technology Stack ### Nutanix: The Infrastructure Foundation Provides the underlying compute, storage, and networking foundation. * High-performance **hyper-converged infrastructure** * **Unified** compute, storage, and networking * Linear **scalability** for growing workloads * **Enterprise-grade** reliability ### Kubernetes: The Orchestration Layer Kubernetes is the core orchestration platform that powers Deploio. * **Industry-standard** container platform * **Automated** container deployment with zero downtime * Built-in **high availability** and failover * **Resource management** across the cluster (without overbooking) * **Self-healing** capabilities with automatic restart * **Zero-downtime** deployments * **Secure** handling of environment variables and secrets * **Automated scaling** based on the number of replicas you have configured ::: info The Kubernetes layer is fully managed by Nine, so you get enterprise-grade orchestration without the operational complexity. ::: ### Deploio: The Magic Glue Deploio is the platform that brings everything together, providing a developer-friendly interface and powerful abstractions on top of the Nine Kubernetes Engine (NKE). * Provides **simplicity** via `nctl` and the Cockpit * Transforms raw Kubernetes into a **developer platform** * Maintains **full Kubernetes compatibility** * **Simplifies configuration** management * **Integrates seamlessly** with development workflows * Supports **multiple programming languages** and frameworks ::: tip You provide the code, we handle the rest. ::: ## Technology Deep Dive ### Container-based infrastructure Deploio runs applications in strictly isolated containers powered by **Kubernetes**, a **battle-tested** container orchestration platform. Deploio, which is built on top of the **Nine Kubernetes Engine (NKE)**, ensures each application and its components are properly separated and isolated from each other, while Kubernetes provides proven reliability through automated scaling, scheduling and container management. Below explains how this infrastructure impacts key operational considerations. #### Safety & Reliability We have used the [FURPS](https://en.wikipedia.org/wiki/FURPS) model to evaluate the safety and reliability of Deploio's infrastructure: ##### Functionality * **Swiss Infrastructure**: Operated under Nine's [AS29691](#swiss-infrastructure-as29691) infrastructure * **Physical Security**: Enterprise-grade data center security measures * **Encrypted Communication**: Secure data transmission protocols ##### Usability * **Access Controls**: Access management via account permissions set at Organisation level * **Familiar Tools**: Manage security through `nctl` and standard Kubernetes commands via `kubectl` * **Unified Interface**: Single platform (Deploio Cockpit) for monitoring via a GUI * **Documentation**: Quick start guides (see sidebar) available for different technologies, as well as general documentation of both Deploio and [Nine products](https://docs.nine.ch/) ##### Reliability * **Kubernetes Backed**: Built on Kubernetes for high availability and reliability * **Automated Recovery**: Self-healing infrastructure * **Backup Systems**: Automated backup procedures ##### Performance * **Low-latency**: Minimal impact on application performance * **Fast CLI Operations**: Quick deployments and updates via `nctl` * **Efficient Container Orchestration**: Kubernetes-powered scheduling, scaling and management * **Configurable Resources**: Control CPU, memory, and storage size for your application * **Zero-downtime Deployments**: Rolling updates without service interruption ##### Supportability * **Management Options**: Maintain your applications easily through either `nctl` CLI or Deploio Cockpit GUI * **Standardized Infrastructure**: Built on enterprise-grade Kubernetes for consistent operations and management * **Flexible Testing**: Create and manage multiple staging environments for thorough testing * **Comprehensive Configuration**: Configure everything from resources and secrets to custom container builds through Dockerfiles * **Simple Onboarding**: Get started quickly with either CLI or GUI-based setup process, backed by clear documentation and quick start guides * **Plug-and-Play Architecture**: Automated container builds with buildpacks and easy integration of services #### Data Loss Deploio’s containerized architecture minimizes service disruption and reduces the risk of data loss during failures. Each container is isolated and automatically restarted if it crashes, with Kubernetes handling recovery by rescheduling Pods or using available replicas to maintain availability. Your application runs in containers with an **ephemeral filesystem**, meaning **any data written to the container's local filesystem will be lost** if the container is restarted, rescheduled, or deleted. ::: warning Important: Understanding Your Application **Your Application = Code (Git) + Runtime Data** Remember: Your application consists of two key parts: * **Code**: Version controlled in Git * **Runtime Data**: Must be stored in persistent services like: * Databases for structured data * S3 for file storage * Redis for caching * Persistent Volume Claims (PVCs) for local persistent storage (not yet available) ::: The ephemeral nature of the filesystem is by design, ensuring clean application states and proper isolation. To persist data across deployments and container lifecycles, you should use **storage services** — such as [managed databases](/user-guide/configuring-your-database.md) or [object storage](/user-guide/other-dependencies.md#object-storage). #### Tenant Separation Applications on Deploio run in containers, which are isolated at the process, filesystem, and network level. These containers are scheduled onto shared cluster nodes **but run independently**. Deploio organizes resources in a clear three-level structure: 1. **Organisation** * Your contract relationship with Nine * The top-level entity that contains all your projects * Manages billing and access control 2. **Projects** * Equivalent to a Kubernetes namespace (1:1 mapping) * Logical grouping of related resources * Provides isolation between different applications or environments 3. **Resources** * The actual components you deploy and pay for: * Applications * Databases * S3 storage * And other services... ::: info Summary Each resource belongs to a project, and each project belongs to your organization, creating a clear and manageable hierarchy for your deployments. ::: However, from an infrastructure perspective, the isolation happens at the **Kubernetes namespace and container level**: * Each project runs in a separate Kubernetes namespace * Each container has its own isolated runtime environment * Resource quotas reflect pricing and network policies reflect security best practices #### Scaling & Reliability Deploio apps run on Kubernetes, which provides built-in orchestration, automatic recovery, and horizontal scaling. By default: * You can scale **vertically** by **increasing CPU and memory limits** for the application * Or scale **horizontally** by **increasing the number of replicas** (number of pods running the application) See [Configuring your Application](/user-guide/configuring-your-application.md) for more details on configuring the scaling. Replicas of your app are distributed across multiple nodes in the cluster, maximizing availability and resilience in case of node failures. Kubernetes continuously monitors the health of your containers and will automatically restart or reschedule them if needed. ### Kubernetes Native Integration Deploio is built as a true Kubernetes extension, not a proprietary abstraction layer. This means: * **Full Kubernetes Compatibility**: Use standard `kubectl` commands * **Familiar Workflow**: If you know Kubernetes, you know Deploio * **Standard Tooling Support**: Works with existing Kubernetes tools, CLIs, and practices For example, you can use familiar commands: ```bash kubectx nineapis.ch kubectl get projects ``` This allows you to manage your Deploio applications using the same Kubernetes tooling and practices you're already familiar with. ::: info You will need to install **kubectl**. ::: ### Swiss infrastructure (AS29691) Deploio is hosted entirely within Switzerland on Nine Internet Solutions AG's infrastructure (AS29691). This provides several key advantages: * **Data sovereignty**: Your applications and data remain within Swiss jurisdiction, ensuring compliance with Swiss data protection laws * **Low latency**: Optimized connectivity for European users with multiple data center locations in Zurich * **Regulatory compliance**: Built-in compliance with Swiss financial and privacy regulations * **High availability**: Redundant infrastructure across independent sites ensures maximum uptime The Swiss hosting ensures your applications benefit from Switzerland's strong privacy laws and political stability, making it ideal for businesses requiring strict data governance. ### Heroku Buildpacks for builds Deploio uses Heroku-compatible buildpacks to automatically detect and build your applications: * **Language detection**: Automatically identifies your application's technology stack (Node.js, Python, Ruby, PHP, Go, Java, etc.) * **Dependency management**: Handles package installation and dependency resolution * **Build optimization**: Caches dependencies between builds for faster deployment times * **Custom buildpacks**: Supports custom buildpacks for specialized requirements * **Zero configuration**: Most applications deploy without any configuration files The buildpack system ensures your applications are built consistently and optimally, regardless of the underlying technology stack. ::: tip Dockerfiles Do you have more granular requirements and need more control over your environment? Don't fret! You can use [**Dockerfile builds**](/docker/quick-start.md) to customize your setup exactly how you want. ::: ### Docker for containerized deployments Every application on Deploio runs in Docker containers: * **Build process**: Applications can be built using either custom Dockerfiles or the aforementioned [buildpacks](#heroku-buildpacks-for-builds) * **Environment reproducibility**: * **Dockerfiles**: Controlled by how you specify base images (tags vs SHA digests) - see [Dockerfile reference](https://docs.docker.com/reference/dockerfile/#from). **You are responsible for maintaining dependencies and configurations.** * **Buildpacks**: Build behavior determined by the buildpack implementation. Deploio detects the language and uses the appropriate buildpack automatically, which uses standardized and maintained base images. * **Dedicated resources**: Unlike shared PaaS platforms, you get 100% of the resources you pay for - no overbooking * **Infrastructure security**: Nutanix provides kernel-level container isolation and security boundaries ::: info The Deploio Guarantee Unlike traditional PaaS providers that may overbook resources across multiple customers, Deploio guarantees dedicated resources for your applications. **The CPU and other resources you pay for are yours.** ::: --- --- url: 'https://guides.deplo.io/docker/quick-start.md' description: >- Quick start guide for deploying applications using custom Dockerfiles on Deploio with build context configuration, build arguments, and best practices for image optimization. --- # Quick Start Guide for Docker Apps (Beta) With Dockerfile builds, Deploio can build any app that can be built using a Dockerfile. ## Example App We have a basic Dockerfile app in our [examples repository](https://github.com/ninech/deploio-examples/tree/main/dockerfile). You can deploy it with [nctl](https://docs.nine.ch/a/85XH6A9bN2/): ```bash nctl create app dockerfile-rust \ --git-url=https://github.com/ninech/deploio-examples \ --git-sub-path=dockerfile/rust \ --dockerfile ``` ## Configuring the Dockerfile to use By default, the `Dockerfile` in your repository root will be used. To use any other file, you can use the flag `--dockerfile-path` to specify a `Dockerfile` at a different location. ```bash --dockerfile-path="path/to/Dockerfile" ``` ## Configuring the Docker build context By default, the build context will be set to your repository root. To use another directory, you can use the flag `--dockerfile-build-context` to specify a different location. ```bash --dockerfile-build-context="path/to/build/context/" ``` ## Ensuring your Dockerfile App releases successfully The Deploio runtime will use the `ENTRYPOINT` and `CMD` specified in the `Dockerfile` to start your application. To serve traffic to your app, the runtime expects it to listen on a TCP socket at `0.0.0.0:$PORT`. The port defaults to `8080` if not specified but can be configured to any valid port number in the app definition. The app health will be checked by a TCP probe to the configured port and traffic only flows to the app once the probe is successful. If the TCP probe fails at any point of the lifecycle, the runtime will restart the app. Also, if the app exits for any reason, it will be automatically restarted. ## Image Size Recommendation Images built with Deploio's Dockerfile build should not exceed 2 GiB uncompressed. There's a hard limit at 10 GiB for the whole build environment but with an image size of more than 2 GiB, the system won't be able to cache all the layers anymore, and you'll notice degraded building performance. ## Build Arguments You can pass [Dockerfile build arguments](https://docs.docker.com/build/building/variables/#build-arguments) via the `--build-env` flag of `nctl`. For example, to define a `ARG` named `APP_VERSION` with a value of `"v0.0.1"` you can use the following format: ```bash --build-env=APP_VERSION=v0.0.1 ``` ## Best Practices Any best practices that apply to Dockerfiles in general will also apply to Dockerfile builds on Deploio. * Try to minimize your image size for faster builds, faster releases and decreased attack surface. * Use [multi-stage builds](https://docs.docker.com/build/building/multi-stage/) for compiled languages whenever possible. --- --- url: 'https://guides.deplo.io/go/quick-start.md' description: >- Quick start guide for deploying Go applications on Deploio using the Heroku Go buildpack with Go Modules and version detection from go.mod. --- # Quick Start Guide for Go Applications The Deploio build environment makes use of the [Heroku Go Cloud Native Buildpack](https://github.com/heroku/buildpacks-go/). ## Example App We have a basic Go app in our [examples repository](https://github.com/ninech/deploio-examples/tree/main/paketo-stack#go). You can deploy it with `nctl`: ```bash nctl create app go \ --git-url=https://github.com/ninech/deploio-examples \ --git-sub-path=paketo-stack/go ``` ## App Requirements Any Go project that meets the following criteria should be buildable: * There is a `go.mod` at the root of the project. * The app compiles with Go 1.16 or greater. * The app uses Go Modules for any dependency installation. ## Go version detection The Go version is read from the `go` line in `go.mod`. This is likely correct for most apps, but a different version may be selected using a [build directive in `go.mod`](https://github.com/heroku/buildpacks-go/tree/main?tab=readme-ov-file#go-version). ## Multiple Binaries The build process will build all main packages that it detects in the project. If you have multiple main packages, you might need to define the desired app entrypoint with a [`Procfile`](https://docs.nine.ch/docs/deplo-io/configuration/deploio-procfile/). For example, if your `main.go` file rests in a directory called `server`, the `Procfile` should look like this: ```yaml web: server ``` This will result in the binary `server` being executed as the app entrypoint. If you want to only build selective packages, you can use a [directive in the `go.mod` file](https://github.com/heroku/buildpacks-go/tree/main?tab=readme-ov-file#package-installation) for that. --- --- url: 'https://guides.deplo.io/nodejs/quick-start.md' description: >- Quick start guide for deploying Node.js applications including Next.js on Deploio using the Paketo Node.js buildpack with npm/yarn build support. --- # Quick Start Guide for Node.js Applications ::: info With our support for the [Paketo Node.js buildpack](https://paketo.io/docs/reference/nodejs-reference/), you can deploy any Node.js application with Deploio. In this guide, we will use a simple Next.js application as an example. ::: ## Prerequisites * This quick start guide assumes you have **installed `nctl` on your computer**. If not, please go through the instructions [here](/user-guide/getting-started.md#installing-nctl). * You should also have an **organization and project created**, where you will create the application. If you haven't done this yet, please follow the instructions [here](/user-guide/getting-started.md#creating-an-account). * This example also presumes that you are **using a public repository**. Should you need to set up access to a private repository, you will need to create an SSH key for security. See more details [here](/user-guide/code-repository-setup.md). ## Use An Existing Application or Create a New One ::: info In this guide, we will use a **Next.js** application for demonstration purposes. However, you can use **any Node.js application** you prefer since the workflow remains the same. ::: In case you don't have a Next.js application yet, you can create one using the Next.js CLI. We recommend following the [official Next.js guide](https://nextjs.org/docs/app/getting-started/installation) to create a new Next.js application. If you want to learn the process, we also provide a basic Next.js app in our [examples repository](https://github.com/ninech/deploio-examples/tree/main/heroku-stack#nodejs). ## Use Git to Store Your Application Deploio requires your application to be **available online** in a Git repository, so that it can be cloned and deployed by the platform. You can use any Git repository hosting service, such as GitHub, GitLab, or Bitbucket. We describe the process of setting up a Git repository [here](/user-guide/code-repository-setup.md). For demonstration purposes, we will use our sample Next.js application hosted on GitHub. ## Create a Deploio Application ::: info Ensure that the **correct project is selected** before creating an application. If you've just created a new project, it's already selected. However, if you want to switch to a different project, you can use the `nctl auth set-project` command. ::: To create an application on Deploio, we can use the `nctl create app` command: ```bash nctl create app nextjs \ --git-url=https://github.com/ninech/deploio-examples \ --git-sub-path=heroku-stack/nodejs/nextjs \ --buildpack-stack=heroku \ --build-env=NODE_ENV="production" \ --env=NODE_ENV="production" ``` This command creates a new application on Deploio using the [Node.js buildpack](https://paketo.io/docs/reference/nodejs-reference/). The `--git-url` flag specifies the URL of the Git repository where the application is stored. The optional `--git-sub-path` flag specifies the subdirectory in the Git repository where the application is located. Finally, the `--env` flag and `--build-env` flag set the `NODE_ENV` environment variable to `production`. ::: warning To ensure the seamless build of your Next.js application, it's crucial to explicitly define the `NODE_ENV` environment variable as `production`. This requirement stems from an existing upstream issue that cannot be rectified. ::: ::: tip Should your project be stored in a private Git repository, you will need to set up an SSH key that allows Deploio to access the repository. Afterwards, you can use the `--git-ssh-private-key` flag or the `--git-ssh-private-key-from-file` flag to specify the SSH key to use. You can find more information on how to do this [here](/user-guide/code-repository-setup.md). ::: After creating the application, Deploio will immediately start cloning your application and attempt to build it by running `npm install` and `npm run build` (or `yarn install` and `yarn build` if you're using Yarn). The Node version is detected by first looking into `package.json` and then into the `engines` field. Should the Node version not be specified in the `package.json` file, the buildpack will fall back to the version specified in the `.nvmrc` file. ## Build env considerations The build process offers a few environment variables which can be used to adjust it to your use-case. See the [how to](https://paketo.io/docs/howto/nodejs/) section of the buildpack documentation for all available variables. If you need to add custom environment variables to your application, ensure that they're available during the build by using the `--build-env` flag when updating your application with `nctl update app`. ### Build an App in a Subdirectory To specify a subdirectory to be used as the root of the app, you can use the `BP_NODE_PROJECT_PATH` build variable. ```bash nctl update app {application_name} \ --build-env=BP_NODE_PROJECT_PATH="./node-app" ``` ## Process customization The Node.js buildpack determines a start command automatically for your app based on the contents of the `package.json` file. However, if you wish to customise the start command, you can do so by declaring a `Procfile` in the root of your app: ```yaml title="Procfile" web: node my-custom-start.js ``` --- --- url: 'https://guides.deplo.io/php/quick-start.md' description: >- Quick start guide for deploying plain PHP applications on Deploio using the Paketo PHP buildpack with configuration for web directories and Composer options. --- # Quick Start Guide for PHP Applications ::: info This guide covers how to deploy a plain PHP application with Deploio. It assumes you have a basic understanding of PHP and Git. ::: The Deploio build environment makes use of the [Paketo PHP buildpack](https://paketo.io/docs/reference/php-reference/). ## Prerequisites * This quick start guide assumes you have **installed `nctl` on your laptop**. If not, please go through the instructions [here](/user-guide/getting-started.md#installing-nctl). * You should also have an **organization and project created**, where you will create the application. If you haven't done this yet, please follow the instructions [here](/user-guide/getting-started.md#setting-up-your-first-project). * This example also presumes that you are **using a public repository**. Should you need to set up access to a private repository, you will need to create an SSH key for security. See more details [here](/user-guide/code-repository-setup.md). ## Use an Existing PHP Application or Create a New One If you do not have a PHP application you want to experiment with, we provide a plain PHP app in our [examples repository](https://github.com/ninech/deploio-examples/tree/main/heroku-stack#php). ## Use Git to Store Your Application Deploio requires your application to be available online in a Git repository, so that it can be cloned and deployed by the platform. You can use any Git repository hosting service, such as GitHub, GitLab, or Bitbucket. We describe the process of setting up a Git repository [here](/user-guide/code-repository-setup.md). For demonstration purposes, we will use our sample PHP application hosted on GitHub. ## Create a Deploio Application To create an application on Deploio, you can use the `nctl create app` command: ```bash nctl create app plain-php \ --git-url=https://github.com/ninech/deploio-examples \ --git-sub-path=heroku-stack/php/plain \ --buildpack-stack=heroku \ --build-env=BP_PHP_WEB_DIR=public \ --build-env=BP_COMPOSER_INSTALL_OPTIONS="--ignore-platform-reqs" ``` Replace the name `plain-php` with any app name best suited for your project. ::: info Beyond the `--git-url` argument that specifies what git repository to deploy, you need to specify a couple of `nctl` options. We will explain those in the next steps. ::: When you create an application, the Git repository is cloned and Deploio will attempt to detect the application type and select the appropriate buildpack. In this case, the [Paketo PHP buildpack](https://paketo.io/docs/reference/php-reference/) will be used. The buildpack will then attempt to detect the desired PHP version from the `composer.json` in the app source. ::: info If your application requires **Node.js** either for the build or runtime, a `package.json` file must be present at the root of the repository for the Node.js runtime to be installed. ::: ## Next Steps The app should be running by now. In the next couple of steps, we explain the various options used when creating the application. Later we will set up a Symfony application and look into how to create databases and other storages. --- --- url: 'https://guides.deplo.io/python/quick-start.md' description: >- Quick start guide for deploying Python Django applications on Deploio using the Paketo Python buildpack with WSGI configuration and environment setup. --- # Quick Start Guide for Python Applications The Deploio build environment makes use of the [Paketo Python Buildpack](https://paketo.io/docs/reference/python-reference/). ## Example App We have a basic Python Django app in our [examples repository](https://github.com/ninech/deploio-examples/tree/main/heroku-stack#python). You can deploy it with `nctl`. The example application shows a random message on every page reload. The Django admin interface can be used to add messages. Just visit `https:///admin` to access it and use the credentials which you pass via the env variables below to log in. Please also define the `SECRET_KEY` which is needed to secure signed data and should be kept secret. ```bash nctl create app django-example \ --git-url=https://github.com/ninech/deploio-examples \ --git-sub-path=heroku-stack/python/django \ --buildpack-stack=heroku \ --env=DJANGO_SU_NAME=admin \ --env=DJANGO_SU_EMAIL=admin@example.com \ --env=DJANGO_SU_PASSWORD= \ --env=SECRET_KEY= ``` ## Build env considerations There are just a few build environment variables supported by the Python buildpack. You can find them in the [Paketo documentation](https://paketo.io/docs/reference/python-reference/). ## Django specifics ### Procfile If you have a Django application, you will need to create a Procfile in the root of your app source code, which changes the default "web" entrypoint to a valid [wsgi project configuration file](https://docs.djangoproject.com/en/4.2/howto/deployment/wsgi/), which will be served by gunicorn. For example, the `Procfile` in our example app looks like: ```yaml web: gunicorn deploio.wsgi ``` ### Configuring `ALLOWED_HOSTS` The `ALLOWED_HOSTS` setting represents the permitted hostnames/domains which the Django site can serve. To allow the default Deploio URLs for your application, you can use the following entry in your `settings.py` file: ```python ALLOWED_HOSTS = [".deploio.app"] ``` Please note that you will need to add all of your custom domain names to this list. So if you want your application to be served on `django-app.example.com` your `ALLOWED_HOSTS` should look like: ```python ALLOWED_HOSTS = [ "deploio.app", "django-app.example.com", ] ``` ### Configuring the `SECRET_KEY` The `SECRET_KEY` parameter is used to secure signed data in Django. It should be kept secure and so not be stored alongside your application code. One way of specifying it is to load it from the environment. You can achieve this by using the following line in your `settings.py`: ```python # The secret key can be passed via the env variable "SECRET_KEY" SECRET_KEY = os.environ.get('SECRET_KEY') if SECRET_KEY == None: raise ValueError("SECRET_KEY environment variable must be set") ``` You then need to specify the environment variable `SECRET_KEY` with `nctl` as you can see in the [Example app section](#example-app). --- --- url: 'https://guides.deplo.io/static-pages/quick-start.md' description: >- Quick start guide for deploying static sites with pure HTML or NPM-based frontends on Deploio with automatic web server configuration and build directory setup. --- # Quick Start Guide for Static Sites If you have a site with purely static content, Deploio makes use of a combination of buildpacks to deploy a web server to serve your static files. ::: info If you're using a **static site generator** like VitePress, Docusaurus, Gatsby, or Astro, see the [Static Site Generators guide](/static-pages/static-site-generators.md) instead. ::: Static sites are detected by looking for these files in your git repo: * `index.html` * `public/index.html` ## Example Apps We have two static sites in our [examples repository](https://github.com/ninech/deploio-examples/tree/main/paketo-stack/#static). You can deploy them with `nctl`: * just a plain `index.html`: ```bash nctl create app static-html \ --git-url=https://github.com/ninech/deploio-examples \ --git-sub-path=paketo-stack/static/html ``` * a frontend react app built with `npm`: ```bash nctl create app static-react \ --git-url=https://github.com/ninech/deploio-examples \ --git-sub-path=heroku-stack/static/react --buildpack-stack=heroku # notice that we use Heroku buildpacks here ``` ## Web server root If you need to modify the location of static files served by the web server, you can set the build environment variable `BP_STATIC_WEBROOT=`. `BP_STATIC_WEBROOT` defaults to `build`. So by default Deploio serves your app from `/workspace/build`. [Vite](https://vite.dev) for example builds into `dist`. So you need to set `BP_STATIC_WEBROOT=dist` which ends up in `/workspace/dist` being served by Deploio's *nginx*. ## NPM Frontend If you have Node modules that need to be installed during the build step, Deploio will detect this using the `package.json` file and run `npm`. In this case, the resulting files will end up in the directory `build`, and it will serve the artifacts from there. --- --- url: 'https://guides.deplo.io/api-examples.md' --- # Runtime API Examples This page demonstrates usage of some of the runtime APIs provided by VitePress. The main `useData()` API can be used to access site, theme, and page data for the current page. It works in both `.md` and `.vue` files: ```md ## Results ### Theme Data
{{ theme }}
### Page Data
{{ page }}
### Page Frontmatter
{{ frontmatter }}
``` ## Results ### Theme Data ### Page Data ### Page Frontmatter ## More Check out the documentation for the [full list of runtime APIs](https://vitepress.dev/reference/runtime-api#usedata). --- --- url: 'https://guides.deplo.io/user-guide/security.md' description: >- Overview of Deploio's security model including TLS, access control, secrets, network boundaries, container isolation, and best practices. --- # Security Deploio is made for the internet. We assume the same of your application. If your security model does not allow unfirewalled HTTP access to port 443 from all over the world, then Deploio is probably not for you. ### Organisation access Access to Deploio is managed per organisation. You can invite users with specific roles (Administrator, Cockpit Access, Technical Contact) to control who can view and manage your projects and applications. See the [Getting started guide](/user-guide/getting-started.md#setting-up-access-within-an-organization) for details on user management. ## Repository access When connecting private repositories, use **deploy keys** (SSH) or **deploy tokens** (HTTPS) rather than personal access tokens. These are scoped to a single repository with read-only access. We recommend the following best practices for repository access: * Grant minimal permissions (read-only) * Use one deploy key per application * Rotate keys periodically For platform-specific setup (GitHub, GitLab, Bitbucket), see [Code Repository Setup](/user-guide/code-repository-setup.md). ::: info Source of Truth Contrariwise to other PaaS providers, operators don't need access to the source code. Code is always pulled by Deploio from a central place. You always know where the deployed code came from. ::: ## Secrets We recommend storing sensitive configuration — database URLs, API keys, credentials — as **runtime environment variables**. These are loaded at boot and are not baked into your container image. ```bash nctl create app my-app \ --env=DATABASE_URL:"postgres://user:password@host/db" \ --env=SECRET_KEY_BASE:"your-secret-key" ``` **Build variables** (`--build-env`) are only available during the build phase and should be used for tools like Webpacker or asset precompilation. Never put runtime secrets in build variables — they may be embedded in the image. For full details, see [Configuring Your Application — Environment Variables](/user-guide/configuring-your-application.md#environment-variables). ## Container ### Buildpack applications When you deploy with buildpacks, Deploio builds your container image automatically. Containers run with **restricted user privileges** (typically `uid=1000`, the `cnb` user). Write access is limited to specific ephemeral directories like `/workspace/tmp`. Buildpack base images are maintained upstream and receive regular security updates. Deploio rebuilds your application on each deploy, picking up the latest base image. ### Dockerfile applications When you use a Dockerfile, **you are responsible for the security of your image**. This includes: * Choosing a secure, maintained base image * Keeping dependencies up to date * Not running as root unless necessary * Not embedding secrets in the image ### Storage limits All containers have a **2 GiB ephemeral storage limit**. If your application exceeds this, the container will be terminated (exit code 137). This storage is not persistent — anything written to the filesystem is lost on restart. ### Disk encryption All of our disks in virtual environments are encrypted at rest. This includes object storage, database disks and ephemeral storage for application containers. Data in transit is encrypted using TLS. ## Network ### Inbound traffic Deploio only proxies **HTTP traffic on a single port**. All external access is HTTPS on port 443, handled by Deploio's ingress layer. No other inbound ports are exposed. Your application sits behind a **TLS-termination proxy** that sets the following headers: | Header | Description | |----------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `X-Forwarded-Proto` | Whether the original connection was HTTP or HTTPS | | `X-Forwarded-Host` | The original domain visited | | `X-Forwarded-For` / `X-Real-Ip` | The client's IP address | | `X-Forwarded-Port` | The original request port | | `X-Original-Forwarded-For` | Contains the value of the X-Forwarded-For header set by a proxy in front of Deploio. This value should only be trusted if the proxy in front of Deploio can be trusted. | ::: warning Deploio does not add security headers like `Content-Security-Policy`, `Strict-Transport-Security`, or `X-Frame-Options`. Your application must set these itself. ::: ### Outbound traffic (egress) Deploio does **not** restrict outgoing traffic. Your applications can access the internet freely — but this means you are fully responsible for the code you deploy and the connections it makes. If you need a **static IP address** for outbound traffic (e.g., to allowlist with an external service), you can configure static egress in the Cockpit under the **Static Egress** tab, or see [docs.nine.ch](https://docs.nine.ch/docs/managed-kubernetes/nke/static-egress-nke/) for details. ## TLS All external access to Deploio applications is exclusively incoming via **HTTPS on port 443**. No other inbound ports are supported. ### Automatic Let's Encrypt certificates Deploio automatically provisions [Let's Encrypt](https://letsencrypt.org/) certificates for every application — for both the default `*.deploio.app` domain and any custom hostnames added by you. Certificates are issued using the **HTTP-01 challenge type**, which means all your custom hostnames must have DNS pointing to Deploio infrastructure before a certificate can be issued for them. For full setup instructions, see [Network & Deployment](/user-guide/network-and-deployment.md#securing-your-application-with-ssl). ::: warning IPv6 Let's Encrypt favors IPv6 (AAAA) DNS records over IPv4. Since Deploio does not currently support IPv6, remove any AAAA records for your custom hostnames when migrating to Deploio — otherwise certificate issuance may fail. ::: ### Custom TLS certificates **Deploio does not support custom TLS certificates.** The industry is moving toward [shorter certificate lifecycles (47 days by 2029)](https://www.digicert.com/blog/tls-certificate-lifetimes-will-officially-reduce-to-47-days), making automated issuance the standard. If you need a certificate authority other than Let's Encrypt that supports automatic issuance, contact support@nine.ch. ## Access Control ### Basic authentication Deploio has built-in HTTP Basic Auth for protecting non-production environments like staging. Credentials are auto-generated and managed by the platform. ```bash # Enable basic auth nctl create app my-app --basic-auth # Retrieve credentials nctl get app my-app --basic-auth-credentials # Rotate the password nctl update app my-app --change-basic-auth-password ``` You can also enable basic auth at the **project level** to protect all applications in a project: ```bash nctl create config --basic-auth -p my-project ``` For full configuration options (including `deploio.yaml` and Cockpit), see [Configuring Your Application — Basic Authentication](/user-guide/configuring-your-application.md#basic-authentication). ## Backups Deploio managed databases (MySQL, PostgreSQL, MariaDB) include **automated daily backups** with a defined retention period. You can manage backups through `nctl` or the Cockpit. Application containers themselves are **stateless** — there is nothing to back up. Your code lives in Git, your configuration in Deploio, and your data in managed databases or object storage. --- --- url: 'https://guides.deplo.io/php/symfony.md' description: >- Guide for deploying Symfony applications on Deploio with configurations for APP_SECRET, web directory, and Composer platform requirements. --- # Setting up a Symfony Application In the previous steps, we have explained the basics of how to set up a PHP application on Deploio. In this step, you will install a Symfony application. This allows us to demonstrate the various storage options in the further steps. ## Example App We have a basic Symfony app in our [examples repository](https://github.com/ninech/deploio-examples/tree/main/heroku-stack#php). You can deploy it with `nctl`: ```bash nctl create app symfony \ --git-url=https://github.com/ninech/deploio-examples \ --git-sub-path=heroku-stack/php/symfony \ --buildpack-stack=heroku \ --env="APP_SECRET=$(openssl rand -hex 8 | tr -d '\n')" \ --build-env=BP_PHP_SERVER=nginx \ --build-env=BP_PHP_WEB_DIR=public \ --build-env=BP_COMPOSER_INSTALL_OPTIONS="--ignore-platform-reqs --no-scripts -o" ``` ### Configure the Application Secret Symfony needs an `APP_SECRET` variable to be defined to a secret value. This is used for security relevant functionality. While it could be read from a `.env` file, it is more secure to set it as an environment variable. We set it to an initial value when creating the application. Unless compromised, the secret should not be changed anymore later on, otherwise existing user sessions will become invalid. ### Configure the Web Directory To avoid exposing random project files to the web, Symfony uses the directory `public` as web root, therefore we need to configure the container to use that directory. ```bash --build-env=BP_PHP_WEB_DIR=public ``` ### Composer Options Symfony uses PHP extensions that are not available on the build system. Additionally, the auto-scripts currently [have to be disabled](https://github.com/paketo-buildpacks/php/issues/284): ```bash --build-env=BP_COMPOSER_INSTALL_OPTIONS="--ignore-platform-reqs --no-scripts -o" ``` --- --- url: 'https://guides.deplo.io/php/background-jobs.md' description: >- Instructions for adding background worker jobs to PHP applications for Symfony Scheduler or Messenger with worker creation, log monitoring, and removal. --- # Setup Background Jobs for your PHP application ::: info Should you require a background process for a worker such as [Symfony Scheduler](https://symfony.com/doc/current/scheduler.html) or [Symfony Messenger](https://symfony.com/doc/current/messenger.html), you can setup a worker command. ::: ## Creating a Worker To add a worker to a running application, you can use the `nctl update application` command. The following example demonstrates how to add a messenger worker for the async queue to the application: ```bash nctl update application {application_name} \ --worker-job-command="bin/console messenger:consume async" \ --worker-job-name "messenger-async" \ --worker-job-size micro ``` The `--worker-job-command` flag specifies the command to run the worker. The `--worker-job-name` flag specifies the name of the worker, and finally, the `--worker-job-size` flag specifies the instance type for the worker, which are the equivalent of the instance types for the application. The available sizes can be viewed [here](https://docs.nine.ch/docs/deplo-io/sizing-overview/). ## Observing a Worker The worker's logs are aggregated with the application logs. You can view all the logs using the `nctl logs` command. If you wish to only view the logs for the worker, you can filter the logs using the `-t, --type` flag: ```bash nctl logs app {application_name} -t worker_job ``` ## Removing a Worker Should you wish to remove a worker from a running application, you can use the `nctl update application` command: ```bash nctl update application {application_name} --delete-worker-job={worker_job_name} ``` ## Next Steps Do you need to **configure Continuous Deployment**? Proceed to the next step. --- --- url: 'https://guides.deplo.io/ruby/background-jobs.md' description: >- Instructions for adding background worker jobs to Rails applications using Solid Queue, GoodJob, or Sidekiq, including worker creation, monitoring, and removal. --- # Setup Background Jobs for your Rails application Are you using Solid Queue, GoodJob or Sidekiq as your background job backend? This guide will show you how to set it up on Deploio. :::tabs key:job-backend \== Solid Queue [Solid Queue](https://github.com/rails/solid_queue) is the default Active Job backend since Rails 8. It stores jobs in your existing PostgreSQL database, so you don't need a Redis instance for it. ### Setup Add Solid Queue to your application: ```bash bundle add solid_queue bin/rails solid_queue:install ``` This generates a configuration file at `config/solid_queue.yml` and a database schema file. ### Single-database configuration By default, Solid Queue is configured to use a separate database. On Deploio, this works with a **Business** database (which gives you a full database server), but not with an **Economy** database (single database). To run Solid Queue on your existing primary database: 1. Copy the contents of `db/queue_schema.rb` into a new migration: ```bash bin/rails generate migration CreateSolidQueueTables ``` Paste the table definitions from `db/queue_schema.rb` into the generated migration file. 2. Point Solid Queue to your primary database: ```ruby # config/environments/production.rb config.solid_queue.connects_to = { database: { writing: :primary } } ``` 3. Run the migration: ```bash nctl exec app {APP_NAME} -- bundle exec rails db:migrate ``` 4. Delete `db/queue_schema.rb` — it is no longer needed. ### Creating the worker ```bash nctl update app {APP_NAME} \ --worker-job-command="bin/jobs" \ --worker-job-name "solid-queue" \ --worker-job-size micro ``` \== GoodJob [GoodJob](https://github.com/bensheldon/good_job) is a PostgreSQL-based backend. Like Solid Queue, it stores jobs in your primary database, so no Redis instance is needed. ### Setup Add GoodJob and run the installer: ```bash bundle add good_job bin/rails g good_job:install bin/rails db:migrate ``` Configure your application to use GoodJob in `config/environments/production.rb`: ```ruby config.active_job.queue_adapter = :good_job ``` ### Creating the worker ```bash nctl update app {APP_NAME} \ --worker-job-command="bundle exec good_job start" \ --worker-job-name "good-job" \ --worker-job-size micro ``` \== Sidekiq [Sidekiq](https://sidekiq.org) uses Redis to store job data. If you haven't set up a key-value store yet, follow the [Key Value Storage guide](./key-value-storage.md) first. ### Setup Add `sidekiq` to your `Gemfile`: ```ruby gem "sidekiq" ``` Configure Sidekiq using your injected variables in `config/initializers/sidekiq.rb`: ```ruby redis_url = "redis://#{ENV['NINE_KVS_REDIS_USER']}:#{ENV['NINE_KVS_REDIS_PASSWORD']}@#{ENV['NINE_KVS_REDIS_FQDN']}:#{ENV['NINE_KVS_REDIS_PORT']}" Sidekiq.configure_server do |config| config.redis = { url: redis_url, ssl_params: { verify_mode: OpenSSL::SSL::VERIFY_NONE } } end Sidekiq.configure_client do |config| config.redis = { url: redis_url, ssl_params: { verify_mode: OpenSSL::SSL::VERIFY_NONE } } end ``` Set Active Job to use Sidekiq in `config/environments/production.rb`: ```ruby config.active_job.queue_adapter = :sidekiq ``` ### Creating the worker ```bash nctl update app {APP_NAME} \ --worker-job-command="bundle exec sidekiq -C config/sidekiq.yml" \ --worker-job-name "sidekiq" \ --worker-job-size micro ``` ::: ## Observing a Worker The worker's logs are aggregated with the application logs. You can view all the logs using the `nctl logs` command. If you wish to only view the logs for the worker, you can filter the logs using the `-t, --type` flag: ```bash nctl logs app {APP_NAME} -t worker_job ``` ## Removing a Worker Should you wish to remove a worker from a running application, you can use the `nctl update app` command: ```bash nctl update app {APP_NAME} --delete-worker-job={worker_job_name} ``` ## Next Steps Do you need to **configure Continuous Deployment**? Proceed to the [next step](./continuous-deployment.md). --- --- url: 'https://guides.deplo.io/user-guide/tools.md' --- # Tools In this guide, we'll introduce you to the tools that you can use to manage your Deploio resources. This section is divided into two categories: * Official tools (actively maintained by Deploio) * Community tools (created and maintained by the community) ## Official ### CLI Our [nctl CLI](https://github.com/ninech/nctl) seamlessly integrates Deploio into your workflows. You can use it to manage applications, databases, and more from the command line. Follow [the Getting Started guide](/user-guide/getting-started.md#installing-nctl) to set it up. Compared to the [Deploio GUI](#gui-cockpit), the CLI interface is more feature-complete and allows you to automate your workflows. In addition, the interface is more stable, making it a great choice for power users. ### API `nctl` is basically a wrapper around the [Nine Self Service API](https://docs.nine.ch/api/). If you're looking for a more programmatic interface, you can of course also call the API directly. #### Using kubectl Nine's API is based on Kubernetes, meaning that you can use `kubectl` to manage your Deploio applications as well. This is especially useful if you're already familiar with Kubernetes and want to use its powerful features. Have a look at [this example](https://docs.nine.ch/api/#section/Introduction/Creating-a-resource-with-curl) showing how an object storage bucket can be created using `kubectl`. #### Create your own GUI/TUI Do you need a GUI/TUI tailored to your specific workflow? Our API provides all the necessary endpoints to build a custom interface for managing your Deploio resources. Have a look at the [API documentation](https://docs.nine.ch/api/) for more details. ### GUI (Cockpit) The [Deploio cockpit](https://cockpit.nine.ch) is a web-based interface that allows you to manage your Deploio resources. It's built on top of the Nine Self Service API and provides a simple and intuitive user interface. It's ideal for quick tasks or when automation isn't required. ## Community This section contains tools created and maintained by the community. Feel free to contribute to them by opening a PR [here](https://github.com/renuo/deploio-guides)! ### deploio-cli The folks at [Renuo](https://renuo.ch) have created a wrapper around [nctl](#cli) that aims to simplify the usage of the CLI. By assuming an [app naming convention](https://github.com/renuo/deploio-cli#app-naming-convention), the CLI will automatically detect the app by matching your git remote URL against nctl apps. This might appeal to developers used to working with Heroku. Note that this CLI is still in early development and not official. ### Claude Code Plugin Also by [Renuo](https://renuo.ch), a [Claude Code](https://claude.ai/code) plugin that lets you deploy and manage Deploio apps using plain-language prompts instead of `nctl` commands. ``` Deploy my Rails app to Deploio My app is throwing 503s, what's wrong? Add a PostgreSQL database and wire it up ``` Five skills cover first-time deployments, day-to-day management, debugging, backing service provisioning, and CI/CD pipeline setup. See the [full guide](/user-guide/claude-plugin.md) for installation and usage. --- --- url: 'https://guides.deplo.io/user-guide/troubleshooting.md' --- # Troubleshooting Should you have an issue with your application, we have a few tools and guides to help you get back on track. ## Logs If you want to debug a runtime error, you could start by looking at the latest logs of your application. Use the following command: ```bash nctl logs app {application_name} --follow ``` See the [Monitoring and Logs](./monitoring-and-logs.md) section for more information. ## Where does it run? To find out under which domain name your app is reachable, you can print a list of verified and unverified hosts: ```bash nctl get app {application_name} ``` If you see entries as "unverified", you need to configure your DNS server. Therefore you can print the DNS target configuration: ```bash nctl get app {application_name} --dns ``` The technical reference has more [details about custom hostname configuration](https://docs.nine.ch/a/myshbw3EY1). ## Which revision is live? ```bash nctl get app {application_name} --output yaml | grep revision ``` Prints the revision of the latest deployment. Use this revision to find the corresponding git commit in the git history. ## Run a command in all your apps If you have many apps you might need to run a command in a container for each application. Use a shell script with `nctl` to generate a list of commands for you: For example if you want to check your *libvips* version for all your apps: ```bash nctl get apps -A -o no-header | while read -r project app _; do printf '%s\n' "nctl exec app $app -p $project --stdin=false -- bash -c \ 'dpkg -l | grep libvips'" done ``` Double-check the output before running. Maybe try it on a few apps at first. The example above assumes a Debian build with *dpkg* available. ## Database ### Access [This guide](./configuring-your-database.md#interacting-with-databases-1) describes how you can access a database directly from your local machine. In case you receive a connection error, make sure that your local IP address is allow-listed in the database configuration. See the [Configuring your database](./configuring-your-database.md#protecting-database-access) guide for more information. ### Backups See the [Database Backups](./configuring-your-database.md#backup-and-restore) guide for instructions on how to create and restore database backups. ## Rollback deployments In case you want to rollback to a previous revision, you can use the following command: ```bash nctl update app {application_name} --git-revision={git_revision} ``` If you're not sure which revision was live, you can find out by looking at release and build information: ```bash nctl get releases nctl get build {build_name} -o yaml | grep revision ``` For rolling back to the previous release you would choose the build of the most recent "superseded" release. ## Kubernetes In case you want to reproduce an issue with a certain build, you can use the following commands to pull the corresponding image and run it locally with Docker or podman: 1. List builds ```bash nctl get builds --application-name {application_name} ``` 2. Pull image for a specific build ```bash nctl get builds {build_name} --application-name {application_name} --pull-image ``` You can also see the full configuration of the build by running: ```bash nctl get builds {build_name} --application-name {application_name} --output json ``` ## Deploio system status We provide further information about the status of our system and services on our [status page](https://status.nine.ch/). ## Support Should you have any other questions or issues, please reach out to us via the following channels. ### Slack Community We do have an official [Deploio Slack community](https://join.slack.com/t/deploiocommunity/shared_invite/zt-3wcpoa6ud-UfQ8JCns6FLe0HLp7s4JdQ). We'll try to answer your questions as soon as possible. ### Contact Next to the Slack community, you can reach us via the following ways: * Email: support@nine.ch * Phone: +41 44 637 40 40 * Support portal: https://portal.nine.ch/ ### Further documentation In case our guides don't cover your issue or question, we provide further documentation [here](https://docs.nine.ch/docs/category/deploio-paas/). --- --- url: 'https://guides.deplo.io/about.md' --- ## What is Deploio? Deploio is a modern, container-based infrastructure platform designed to simplify deployment processes and streamline application management. It provides developers with tools to easily deploy, manage, and scale their applications, reducing the complexity of infrastructure handling. ### Key Features: * **Seamless Deployment:** With tools like `nctl` and an intuitive UI, Deploio makes deploying applications fast and hassle-free. * **Integrated Solutions:** Includes built-in monitoring, database management, and automation tools to reduce operational overhead. * **Scalable Infrastructure:** Supports container-based deployments, allowing your applications to scale effortlessly. ## Who Can Benefit from Deploio? Deploio is tailored for developers and teams who want a more efficient, automated way to manage their deployment workflows. ### Why Choose Deploio? * **Simplified Workflows:** Streamline the deployment process, saving time and effort. * **Automation Ready:** Enable scripting and automation for repetitive tasks. * **Centralized Management:** Manage monitoring, databases, and deployments from a single platform. ## About Nine & Renuo Deploio is the result of a collaboration between **Nine** and **Renuo**, two companies committed to delivering innovative solutions for developers. Their partnership has created a platform that integrates seamlessly within their ecosystem, supporting development teams with robust and reliable infrastructure. ### Nine A leading provider of managed services and cloud hosting solutions, Nine brings years of experience in reliable infrastructure and enterprise-level scalability. ### Renuo A development company focused on creating elegant software solutions. Renuo’s expertise in modern development practices complements Nine’s infrastructure capabilities. Together, Nine and Renuo ensure that Deploio offers the perfect blend of reliability, usability, and innovation for developers and teams. ## Why Deploio Stands Out * **Developer-Centric Design:** Built with developers in mind, ensuring a smooth and intuitive experience. * **Collaborative Ecosystem:** Backed by trusted companies with a history of delivering high-quality solutions. * **Future-Ready Infrastructure:** Supports modern deployment practices with containers and automation. Explore how Deploio can simplify your deployment workflows and let you focus on building great applications! --- --- url: 'https://guides.deplo.io/php/extensions.md' description: >- Instructions for loading PHP extensions using Composer requirements or custom .ini files with the Paketo buildpack's pre-built extension support. --- # Using Extensions PHP extensions need to be installed into the server running PHP. This needs to be done before your container is started. As mentioned in the introduction, Deploio uses the [Paketo PHP buildpack](https://paketo.io/docs/reference/php-reference/) for providing PHP support. This includes the [Paketo php-dist buildpack](https://github.com/paketo-buildpacks/php-dist) which provides the PHP binary distribution. The built PHP binary distribution includes a number of extensions which can be used in your PHP application on Deploio. All of them are defined in separate yaml files per PHP version in the [Paketo php-dist buildpack](https://github.com/paketo-buildpacks/php-dist/tree/main/dependency/actions/compile/extensions-manifests). If you need extensions that are not defined in the above-mentioned files, you will need to [provide your own Dockerfile](../docker/quick-start.md). Be aware that none of the pre-built extensions get loaded by default (due to memory usage optimizations). You have to specify the extensions your application needs either in the requirements section of your composer.json or with `*.ini` files. Both approaches will be explained in the following sections. ## Loading Extensions via Composer If you are using [Composer](https://getcomposer.org/) as a package manager, you should specify your necessary extensions in the `require` section of your `composer.json` file. For example, to load the curl, gd and zip extensions, specify: ```json title="composer.json" { "require": { "php": "^8.1", "ext-curl": "*", "ext-gd": "*", "ext-zip": "*" } } ``` It is best practice to declare all required PHP Extensions in composer.json, see also the [official composer documentation](https://getcomposer.org/doc/articles/composer-platform-dependencies.md#composer-platform-dependencies). ## Loading extensions via custom .ini files If you are not using Composer, you need to provide custom `*.ini` files to load extensions. The files need to be located at `/.php.ini.d/*.ini` in your application source code repository. For example, to load the curl, gd and zip extensions, you could create a file `/.php.ini.d/custom-extensions.ini` with the following content: ```ini title="/.php.ini.d/custom-extensions.ini" extension=curl.so extension=gd.so extension=zip.so ``` ## Composer Platform requirements As the build and runtime containers are different on Deploio, you may run into issues where you cannot build a project successfully due to platform requirements not being fulfilled by the build-time container. You can ignore these requirements using: ```bash --build-env=BP_COMPOSER_INSTALL_OPTIONS="--ignore-platform-reqs" ``` which will ignore all build requirements, or you can scope it to specific extensions: ```bash --build-env=BP_COMPOSER_INSTALL_OPTIONS="--ignore-platform-req=ext-mysqli" ``` When doing this, you will see from the logs that the buildpack still validates that the extensions you require are available in the runtime image, but the build will no longer fail due to the build container missing extensions. ## Next Steps In the next step, we will look at some more options to configure how your application needs to be run. --- --- url: 'https://guides.deplo.io/introduction/about-deploio.md' description: >- Introduction to Deploio, a container-based platform by Nine and Renuo that simplifies application deployment with seamless workflows and integrated solutions. --- # What is Deploio? Deploio is a modern, container-based infrastructure platform designed to simplify deployment processes and streamline application management. It provides developers with tools to easily deploy, manage, and scale their applications, reducing the complexity of infrastructure handling. ### Key Features: * **Seamless Deployment:** With tools like `nctl` and an intuitive UI, Deploio makes deploying applications fast and hassle-free. * **Integrated Solutions:** Includes built-in monitoring, database management, and automation tools to reduce operational overhead. * **Scalable Infrastructure:** Supports container-based deployments, allowing your applications to scale effortlessly. ## Who Can Benefit from Deploio? Deploio is tailored for developers and teams who want a more efficient, automated way to manage their deployment workflows. ### Why Choose Deploio? * **Simplified Workflows:** Streamline the deployment process, saving time and effort. * **Automation Ready:** Enable scripting and automation for repetitive tasks. * **Centralized Management:** Manage monitoring, databases, and deployments from a single platform. ## About Nine & Renuo Deploio is the result of a collaboration between **Nine** and **Renuo**, two companies committed to delivering innovative solutions for developers. Their partnership has created a platform that integrates seamlessly within their ecosystem, supporting development teams with robust and reliable infrastructure. ### Nine A leading provider of managed services and cloud hosting solutions, Nine brings years of experience in reliable infrastructure and enterprise-level scalability. ### Renuo A development company focused on creating elegant software solutions. Renuo’s expertise in modern development practices complements Nine’s infrastructure capabilities. Together, Nine and Renuo ensure that Deploio offers the perfect blend of reliability, usability, and innovation for developers and teams. ## Why Deploio Stands Out * **Developer-Centric Design:** Built with developers in mind, ensuring a smooth and intuitive experience. * **Collaborative Ecosystem:** Backed by trusted companies with a history of delivering high-quality solutions. * **Future-Ready Infrastructure:** Supports modern deployment practices with containers and automation. Explore how Deploio can simplify your deployment workflows and let you focus on building great applications!