Docs / Getting Started / Your First Deploy

Your First Deploy

Put your own code online from a directory on your machine, with no Git repository needed. Every command below was run against a sh0 server, with its real output.

Overview

sh0 deploys an app from four sources. This guide follows the first one, which suits most projects:

  • A directory on your machine, sent by sh0 push as an archive -- your code, with a Dockerfile or a detected stack (Node.js, Python, Go, Rust, PHP…).
  • A ZIP archive uploaded from the dashboard.
  • A Git repository, public or private, cloned by the server.
  • A template from the catalogue (databases, CMS, tools).

Step 1: Prepare the directory

A Dockerfile at the root gives you full control over the image. Without one, sh0 detects the stack from the project's files. The app must listen on a port, here 3000:

Dockerfile
FROM node:20-alpine
WORKDIR /app
COPY server.js .
EXPOSE 3000
CMD ["node","server.js"]

sh0 check scores the directory before anything is sent and points out what to fix. sh0 push runs the same check and stops on a blocking issue (unless --no-check); warnings do not stop it:

Terminal
$ sh0 check .
  Scanning /home/you/my-api
  Detected:  Dockerfile

  Health Score: 95/100
  Complexity:   2 (Simple)

  [~] Warnings (1):
      - Missing .dockerignore
        Fix: Create a .dockerignore file with: node_modules, .git, dist, .env

  1 issue(s): 0 blocking, 1 warnings, 0 auto-fix, 0 info

Step 2: Connect the CLI

Install the CLI on your machine (see CLI installation), then run sh0 login --url https://panel.example.com with your panel's address. It asks for your email and password (and your 2FA code if enabled), then stores an API key in ~/.sh0/config.toml.

Check the connection:

Terminal
$ sh0 whoami
  Server:  https://panel.example.com
  User:    [email protected]
  Role:    owner

Step 3: Push

From the project directory:

Terminal
$ sh0 push -n my-api --port 3000
  Deploying my-api
  Detected dockerfile -- 95/100 health
  2 files (0.0 MB) packaged
  Uploading OK 5ms
  Routing OK 10.0s

[ok] Live in 10.0s
  -> https://my-api-<instance>.sh0.app
  • -n names the app; without it, the directory's name is used. The same name later updates the same app.
  • --port is the port your app listens on inside the container.
  • An archive is limited to 500 MB. Add a .dockerignore to leave out node_modules, .git and build output; see Push to deploy for the other limits.

Step 4: Verify

The last line of sh0 push is the app's address. On a server connected to the sh0 cloud proxy it is a *.sh0.app subdomain with HTTPS; on your own domain, see step 6.

Terminal
$ sh0 status my-api
  App: my-api
  ------------------------------
  ID:         85aab295-4166-470a-9538-807b46e8bec3
  Status:     running
  ...
  Latest Deployment
  ------------------------------
  ID:         551c1602-5a46-49eb-93df-70ee831cfea3
  Status:     running
  Duration:   37.9s
  When:       39s ago

$ curl -s https://my-api-<instance>.sh0.app/
{"db":true,"version":2,"greeting":"salut"}

If the app does not answer, read its logs with sh0 logs my-api --tail 100, or open the app in the dashboard and look at the deployment's build log.

Step 5: Update

Change your code and run the same sh0 push -n my-api --port 3000 again: sh0 builds a new image and replaces the running container once the new one is ready. The update above took 38 seconds, and the app answered with its new version.

Step 6: Your own domain

Point an A record of your domain to the server's IP address, then add it to the app, from the app's Domains tab or with sh0 domains my-api add api.example.com. sh0 requests the TLS certificate from Let's Encrypt. Details in Custom domains.

Warning
Add the domain once the DNS record resolves to the server. Before that, the certificate request fails, and Let's Encrypt limits repeated failures.

From the dashboard

Open Deploy in the sidebar and choose a source:

  • File Upload -- a ZIP archive of your project.
  • Git URL or GitHub -- a repository and a branch.
  • Template -- an application from the catalogue.
Note
For a private repository, give an access token in the Access Token field, or use an SSH key added to the server; see Git deploy.

What's Next

Your app is online. Next steps: