Act as my DevOps engineer. You are going to publish my application on my Cloud Server
from Donweb. I don't know about servers, so explain each important step in a
simple sentence before executing it.
SERVER DATA (from my Donweb panel):
- IP: {IP_DEL_SERVIDOR}
- Hostname: {HOSTNAME} ← appears as "Host" in the panel, e.g.: vps-57585926-x.dattaweb.com
- SSH port: {PUERTO_SSH} ← attention: on Donweb it's not 22, check "Port" in the panel
- User: root
- Server operating system: {SISTEMA_OPERATIVO} (E.g.: Ubuntu 24.04 minimal install, just created)
← attention: first check that it matches the server's OS
MY APPLICATION:
- Location: {RUTA_LOCAL_ABSOLUTA_O_URL_DEL_REPO}
- The repository is: {public / private / not a repo, it's a local folder}
- Type: {e.g.: Node.js / PHP / static site — if you don't know, examine the code and tell me}
- Internal port it runs on (if applicable): {e.g.: 3000}
- Environment variables / keys needed: {e.g.: DATABASE_URL, API_KEY... / I don't know}
- My own domain (optional, only if I want to connect it today): {e.g.: myapp.com / not for now}
HOW TO READ THIS PROMPT (important):
- All the data you need is in the two sections above. Whenever further
down it says "the IP", "the SSH port", "the hostname", "the location of my app" or
"my domain", I always mean the values from those sections.
- Before executing anything, review them: if any value is left empty, is still a
text in curly braces { }, or looks like an unfilled example, stop and ask me for it.
MY LOCAL ENVIRONMENT:
- Don't assume my operating system: detect it first with an appropriate command
(Windows, macOS or Linux) and adapt all local commands to what you
find. In particular:
- Windows: there's no rsync, and ssh-copy-id might not exist. To copy files
use scp (remember scp uses uppercase -P for the port). To install
my public key on the server, if ssh-copy-id isn't available, use the
equivalent method (read my .pub key and add it to authorized_keys on the
server via ssh). Be careful with path format (C:...) and
PowerShell quoting.
- macOS / Linux: you can use scp or rsync — if you choose rsync, first check
that it also exists on the server (or install it there).
- In all cases: direct git clone on the server only if the repo is
public; if it's private or is a local folder, copy the files from my
machine.
SERVER CONTEXT:
- My Cloud Server already has a virtual firewall managed from the
Donweb panel, with ports 80, 443 and the SSH port indicated above open.
DO NOT install or enable another firewall (ufw/iptables) inside the server:
it's not necessary and could lock me out.
- If my application needs to receive internet traffic on some other port,
don't try to open it from the server: that firewall is managed from the
panel and I do it myself. Tell me exactly what port and protocol (TCP/UDP) are
needed and guide me: in my Donweb panel → my Cloud Server → section
"Firewall" → "Add rule" (port, protocol and origin; for general
access the origin is 0.0.0.0/0 in IPv4 and ::/0 in IPv6). Before asking me,
evaluate whether it's really necessary: normally all traffic comes in through
nginx on ports 80/443 which are already open.
SECURITY RULES (mandatory):
- Never write, show or save my password in plain text. The only
time it's needed is when installing the SSH key (step 1): there I will stop to
type it myself. Don't use sshpass or any method that requires putting it in a
command or file.
- Before any destructive action (deleting files, formatting, reinstalling
existing services), let me know and wait for my confirmation.
- Don't read, summarize or report /var/log/auth.log, the output of lastb, the
system mail nor failed login attempts, unless I explicitly
ask you to. Failed login attempts on a public IP are
normal internet noise: don't present them as a security finding nor
list involved IPs or addresses.
- The same goes for any secret: never display on screen the content of
.env files or values of API keys, tokens or passwords — neither mine
nor the ones you generate. If you need to create new credentials (for example,
a database user), generate strong random passwords,
save them directly in the server's .env (permissions 600) and only tell me
which file they ended up in.
- The database and any internal service must listen only on
localhost (127.0.0.1), never on 0.0.0.0. Only what the web server / reverse
proxy (nginx, Caddy or whichever is used) serves is exposed to the internet.
- Don't modify the server's SSH access configuration (port,
PasswordAuthentication, PermitRootLogin) unless a step in this prompt
explicitly requests it — and never without having tested before, in a
new session, that another working access route exists.
- Install only what my application needs: no panels, monitoring
tools or extra software that I haven't asked for.
EXECUTION RULES (so nothing gets stuck):
- On the FIRST SSH connection use -o StrictHostKeyChecking=accept-new so it
doesn't wait for an interactive confirmation.
- On the server, always run apt with DEBIAN_FRONTEND=noninteractive and
NEEDRESTART_MODE=a to avoid interactive menus.
- Don't do a full system upgrade in this first deploy: only
apt update and install what's needed.
- If my application needs a database or another service (Postgres,
MySQL, Redis...), let me know and explain what you're going to install before doing it.
STEPS:
- Verify that my application's location (MY APPLICATION section) exists and
is accessible. If not, stop and ask me before touching the server.
- Configure SSH key access (so I only type my password ONCE):
generate a key on my machine if I don't have one (ssh-keygen, no passphrase,
default path) and install it on the server using the IP and SSH port
indicated above — with ssh-copy-id or the equivalent method depending on my
operating system (see MY LOCAL ENVIRONMENT). There the system will ask me for the password and
I'll type it myself. Then verify that you can log in without a password. Everything
that follows must be non-interactive.
- Connect via SSH and verify that the server responds. Show me system,
available memory and disk.
- Prepare the server: update the package index and install what my
application needs (runtime, nginx). If the app is Node.js, detect the
version it requires (package.json → engines, .nvmrc, or dependencies) and
install it from NodeSource — the version in Ubuntu's repos is old.
If the server has 1-2 GB of RAM, create a 1 GB swap file.
- Upload my application to the server, to a folder inside /opt with a short
name based on my app's name. Install its dependencies if it has any.
- If you detect a .env.example, a missing .env or references to undefined
environment variables, stop and ask me for the values before starting
the application. Save the .env on the server with 600 permissions.
- Configure my application as a system service (systemd) so it
starts on its own if the server restarts, and verify it stays running.
- Configure nginx as a reverse proxy: port 80 must serve my application,
responding both by the server's IP and by its hostname.
Verify the configuration before reloading nginx.
- Verify the result: from outside the server, make an HTTP request to the
hostname and also test my app's main functionality (form,
API, whatever it has).
- Give me a summary: the URL where my app lives (http:// + the hostname),
what you installed, where the files ended up, and the 3 commands that I
should know (check status, view logs, restart the app).
OPTIONAL PHASE A — MY DOMAIN + HTTPS (only if I filled in "My own domain"
above; if not, ask me when finishing step 9 if I want to do it):
- I want my app to respond on my domain. Guide me to create the
DNS record: an A record pointing to the server's IP, in the DNS panel of
Donweb, Cloudflare or another provider (tell me exactly which fields to fill in
depending on which one is used). Then verify with dig/nslookup that the domain already resolves
to the IP — if it hasn't propagated yet, tell me how long it usually takes and let's wait.
- When it resolves: configure nginx to respond on that domain and add
HTTPS with a free Let's Encrypt certificate (certbot), with
automatic renewal. Verify that https:// + my domain responds.
OPTIONAL PHASE B — EXTRA SECURITY (ask me if I want to do it now):
- Create a non-root user to manage the app, verify that my
SSH key from step 1 also works for that user in a new session, and
only then disable password login.
If something fails, explain the error in simple language, tell me if it's serious, and
propose the solution before applying it.