---
title: "Deploy your first app to a server with erpc worker"
description: "Make the HelloWorld app with erpc worker, run it on your machine, and deploy it to an ERPC VPS or a server of your own."
canonical: "https://erpc.global/en/doc/erpc-cli/worker-quickstart/"
locale: "en"
---

# Deploy your first app to a server with erpc worker

Make a small HTTP API in Rust with `erpc worker`, run it on your machine, and deploy it to a server with four commands.

This page describes ERPC CLI `v0.1.0-rc.4`, a pre-release.

`erpc worker` (alias `erpc w`) compiles your app to a native Linux binary and runs it on an ERPC VPS, a new hourly one, or a server of your own, under a hardened systemd unit with no Docker and no runtime in between.

A release that does not come up healthy is rolled back to the one before, and several apps can share one server, each on a port of its own. Everything about the app is in `erpc.toml` at its root, which holds no secret and can be committed.

## Prerequisites

- **An ERPC account**, signed in on this machine with `erpc login` ([Sign in and keys](https://erpc.global/en/doc/erpc-cli/sign-in-and-keys/)).
- **ERPC Credit**, for a new hourly VPS. An hourly product is paid from ERPC Credit, which is bought beforehand, and a start the credit does not cover is refused. Prices are on [Pricing](https://erpc.global/en/price/) and the [ERPC Web Dashboard](https://dashboard.erpc.global/en).
- **An SSH key** on this machine: `ssh-keygen -t ed25519`, or `erpc config set ssh_key <path>.pub` for a key you have.
- **A way to build for Linux.** From a Mac or Windows, the Rust target for the server (`rustup target add x86_64-unknown-linux-gnu`), `zig` (`brew install zig` on macOS) and `cargo-zigbuild` (`cargo install cargo-zigbuild --locked`). From a Linux machine of the server's kind (x86-64 for every ERPC server), nothing more than cargo. Without the cross-build tools, the app is built with this machine's own toolchain, and the binary then needs the glibc it was linked against, which `build` and `deploy` name. With them, it is built for glibc 2.31 and up.

## Deploy HelloWorld

HelloWorld is a small HTTP API in Rust that needs no key, no secret and no data line. It answers `GET /`, `GET /hello/{name}` and `GET /healthz`.

```bash
erpc worker init --template helloworld   # makes ./hello-world
erpc worker run hello-world              # here: curl http://127.0.0.1:3000/
erpc worker deploy hello-world           # your VPS, or a new hourly one (price asked first)
erpc worker api / --dir hello-world      # {"message":"Hello, World!",…} from the server
```

1. `init` makes the app in `./hello-world`, with its `erpc.toml`.
2. `run` builds the app and runs it on your machine, so you can call it with curl first.
3. `deploy` builds it for the server and deploys it. Anything that costs money is shown first with its hourly price, your balance and how long the credit lasts, and at a terminal it starts only after a yes.
4. `api` calls the deployed app's API from your machine, with the API still on the server's loopback.

`erpc worker check` lists what the app is missing, and `deploy` refuses before it buys anything when something is. `erpc worker build` runs the build alone, the way to see a build fail before a server is bought.

## Choose a template

`erpc worker init` asks one thing: what to make, picked with the arrow keys.

- **HelloWorld** is the one to start from.
- **HFT** and **pumpfun-bot** are both made from the pumpfun template for now: a pump.fun (PumpSwap) trading bot ported from ValidatorsDAO/solana-stream.

`--template hft` (or `helloworld`, `pumpfun-bot`, or a template id) skips the picker, and `--name` names the app. Without a name, the app is named after the choice (`hello-world`, `hft-bot`, `pumpfun-bot`). When a directory of that name exists, a person picking gets `-2`, `-3` and so on, and a script (`--yes`, `--json`, no terminal) gets an error. With nobody to ask and no `--template`, HelloWorld is what is made.

A trading bot needs a key and a few settings before it runs. Its order:

```bash
erpc login                             # once per machine: the session in 1Password or the keychain
erpc worker init                       # pick with the arrow keys; makes ./<name> with erpc.toml
cd <name>
erpc worker key new                    # the trading key, in 1Password, the keychain or the keystore; prints the public key to fund
erpc worker secret put API_TOKEN --generate          # the bot's own API token, made for you and shown to nobody
erpc worker secret put ERPC_API_KEY --from-account   # the account's RPC key, read from your account (or SOLANA_RPC_ENDPOINT in [vars])
erpc worker check                      # what erpc.toml describes, and what is missing
erpc worker run --grpc --ip <IPV4>     # build and run here, with an hourly gRPC line letting this machine in
erpc worker run --check --grpc --ip <IPV4>   # the same, stopped once healthy
erpc worker deploy --new-vps --grpc    # a new hourly VPS and gRPC line, prices asked first
```

`init` prints this order for the app it made. [Keys and secrets](https://erpc.global/en/doc/erpc-cli/worker-secrets/) covers where the key and the secrets are kept.

## Choose the server

`deploy` uses the first of these:

1. the server the app's `[env.<name>]` already names;
2. `--vps <id>`, an ERPC VPS of your account;
3. `--new-vps`, the cheapest hourly VPS in the region nearest this machine by its time zone (`--region` and `--plan` choose otherwise);
4. `--host <address>`, a server of your own: Ubuntu or Debian with systemd, nftables, `sudo` and Python 3 at `/usr/bin/python3`, reached as root or a user with passwordless sudo;
5. otherwise, at a terminal, a list of your account's running VPSs, with "start a new one" at the end.

On a server of your own, the worker's firewall drops every inbound connection but SSH and the app's port, so a server that serves anything else is not the one to use.

## Deploy without a person at the terminal

A script, or an agent such as `erpc ai`, has no terminal to answer at. Two flags let it do the work all the same:

```bash
erpc worker deploy hello-world --new-vps --yes                     # no key: all the way, unattended
erpc worker deploy pump-sniper --new-vps --grpc --yes --prepare    # a bot: everything but its key
erpc worker deploy pump-sniper                                     # then you, at a terminal: the key, and the start
```

- **`--yes`** answers the price of each hourly product the command names (`--new-vps`, `--grpc`, `--shreds`, `--unlimited`). It also answers the first login to a server erpc has not made key-only yet, a new one or one named with `--vps <ID>`: erpc logs in once with the server's password, puts your key in and turns password logins off. Without `--yes` and without a terminal, a start is refused before anything is bought, with exit status 3.
- **Choosing among your servers still needs a person.** Name the server with `--new-vps`, `--vps <ID>` or `--host`.
- **`--prepare`** does everything that needs neither the trading key nor a secret, and starts, stops and restarts nothing. The next `erpc worker deploy` at a terminal hands the key and the secrets over and starts the app. The trading key is read only for a person at a terminal.

## Connect your app to gRPC, Shreds and Unlimited RPC

ERPC's hourly lines admit the server by its address and take no token. One flag on `deploy` starts each line for the server, and the app gets its endpoint as a setting:

| Flag | Line | The app gets |
| --- | --- | --- |
| `--grpc` | Geyser gRPC | `GRPC_ENDPOINT` |
| `--shreds` | Shreds (Shredstream gRPC) | `SHREDS_ENDPOINT` |
| `--unlimited` | Unlimited RPC in the server's region | `SOLANA_SEND_RPC_ENDPOINT` |

- Each line is the cheapest of its family unless `--grpc-plan`, `--shreds-plan` or `--unlimited-plan` names one.
- The Unlimited RPC runs on a dedicated server that takes up to 45 minutes to set up. It serves `sendTransaction` and a short list of reads, not `getProgramAccounts` or `getTokenAccountsByOwner`. Its endpoint is plain HTTP (no TLS) and admits only the whitelisted address.

### Lines for a run on your machine

`erpc worker run` takes `--grpc` and `--shreds` too, for trying the app here against real data before it goes to a server.

- **The address:** the lines admit this machine's public IPv4 address, which you pass with `--ip`. erpc does not look it up itself.
- **Buying:** a new line is bought only at a terminal, after its price is shown. `run` has no `--yes`.
- **Ending:** when the run ends, each hourly line is ended after asking. `--keep-lines` keeps them, still charged. If the run ends any other way (the terminal closed, a second Ctrl-C), the lines stay and are charged.
- **The numbers:** what the app measures here includes the distance from this machine to the line, so it is slower than the same app on a server near it.

## Next steps

- [Import an app](https://erpc.global/en/doc/erpc-cli/worker-import/): Deploy an app you already have, in any language.
- [Keys and secrets](https://erpc.global/en/doc/erpc-cli/worker-secrets/): Keep a trading key and secrets off the server's disk.
- [Firewall and WAF](https://erpc.global/en/doc/erpc-cli/worker-firewall-and-waf/): Put a public API behind a WAF.
- [Status and billing](https://erpc.global/en/doc/erpc-cli/worker-status-and-billing/): Watch the app and see what it costs by the hour.
