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 pushas 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:
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:
$ 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 infoStep 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:
$ sh0 whoami
Server: https://panel.example.com
User: [email protected]
Role: ownerStep 3: Push
From the project directory:
$ 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-nnames the app; without it, the directory's name is used. The same name later updates the same app.--portis the port your app listens on inside the container.- An archive is limited to 500 MB. Add a
.dockerignoreto leave outnode_modules,.gitand 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.
$ 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.
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.
What's Next
Your app is online. Next steps:
Learn about Stacks
Understand how to organize multiple apps and services.
Environment Variables
Add configuration and secrets to your app.
Domains & SSL
Set up custom domains and understand SSL automation.
Add a Database
Create a PostgreSQL, MySQL, MariaDB or Redis server and connect your app to it.