Ihre App läuft auf localhost. Jetzt möchten Sie sie über eine echte Domain teilen, ohne dass Ihr Laptop dauerhaft laufen muss. Dafür fehlen noch ein VPS, ein verwalteter Anwendungsprozess, DNS und ein HTTPS-Reverse-Proxy.
Dieser Ratgeber zeigt diesen Weg anhand einer kleinen Node.js-App. Claude Code kann Ihnen helfen, Ihr Projekt zu untersuchen und Konfigurationen zur Prüfung vorzubereiten; für die Änderungen am Server bleiben Sie selbst verantwortlich. Das Modell wird nicht auf dem VPS installiert, und Claude-Zugang und Abrechnung sind vom Hosting getrennt.
Animierte Anleitung. Das Dashboard ist eine fiktive Demonstration und kein Live-Infrastruktur-Monitoring.
Überblick über die Bereitstellung ansehen
Überblick zur Bereitstellung ansehen (Video auf Englisch).
Was wir tatsächlich getestet haben: Ein echtes Dashboard, das ursprünglich von Claude Code erstellt wurde, wurde von unserem Operator auf einem Wegwerf-Linux-VPS bereitgestellt. Wir haben öffentliches DNS, vertrauenswürdiges HTTPS, die Weiterleitung von HTTP auf HTTPS, Anwendungs- und Proxy-Prozesse ohne Root sowie den Zugriff nach einem Neustart des Anwendungsdienstes überprüft. Es gab keinen neuen autonomen Deployment-Lauf von Claude. Der unten vorgeschlagene Prompt dient der Anleitung und ist keine aufgezeichnete Antwort.
Bevor Sie beginnen
- Ein Linux-VPS mit systemd und ein SSH-Konto mit sudo-Zugriff. Verwenden Sie zuerst einen Test-VPS; überschreiben Sie nicht die Dienste oder die Webkonfiguration einer bestehenden Website.
- Eine unterstützte Node.js-LTS-Laufzeit, die für den Server installiert ist, und Caddy als installierter Systemdienst. Installieren Sie diese Voraussetzungen, bevor Sie den Schritten zur Bereitstellung folgen.
- Eine Domain oder Subdomain, deren DNS-Einträge Sie bearbeiten können.
- Eine kleine, eigenständige App. Unser Beispiel liefert
index.htmlmitserver.mjsaus, ohne Paketabhängigkeiten und ohne Datenbank.
Framework-Anwendungen benötigen eigene Build-Befehle, Startbefehle, Abhängigkeiten und ein eigenes Speicherkonzept. Gehen Sie nicht davon aus, dass ein Projekt mit Next.js, Python oder Datenbank dieses Beispiel aus zwei Dateien unverändert nutzen kann.
1. Claude Code das Projekt untersuchen lassen, bevor etwas geändert wird
Starten Sie in Ihrem lokalen Projektverzeichnis. Eine nützliche erste Anfrage lautet:
Inspect this project without changing files. Identify its runtime,
build and start commands, configuration and secrets. Propose a Linux
VPS deployment using a non-root systemd service and Caddy HTTPS.
Bind the app to 127.0.0.1:3000. Explain each proposed file and
verification step. Do not connect to a server or edit DNS.
Die dokumentierten Workflows von Claude Code umfassen die Planung vor dem Bearbeiten. Prüfen Sie die vorgeschlagenen Änderungen, statt Deployment-Befehle blind zu übernehmen. Halten Sie API-Schlüssel, Produktionszugangsdaten und private SSH-Schlüssel aus Prompts und Repositories heraus; ein schreibgeschützter Zugriff macht sensible Dateien nicht vertraulich.
2. Die Anwendung vorbereiten und übertragen
Speichern Sie für dieses minimale Beispiel Ihr HTML als index.html und verwenden Sie den folgenden Server. Er bindet standardmäßig an Loopback und gibt keine beliebigen Projektdateien frei:
import {createServer} from 'node:http';
import {readFileSync} from 'node:fs';
import {fileURLToPath} from 'node:url';
const page=readFileSync(new URL('./index.html',import.meta.url));
export function createAppServer(){
return createServer((req,res)=>{
const pathname=new URL(req.url,'http://localhost').pathname;
if(pathname!=='/' && pathname!=='/index.html'){
res.writeHead(404,{'Content-Type':'text/plain; charset=utf-8'});res.end('Not found');return;
}
res.writeHead(200,{'Content-Type':'text/html; charset=utf-8','X-Content-Type-Options':'nosniff'});res.end(page);
});
}
if(process.argv[1]===fileURLToPath(import.meta.url)){
const host=process.env.HOST||'127.0.0.1';const port=Number(process.env.PORT||3000);
const server=createAppServer();server.listen(port,host,()=>console.log(`Demo app listening on ${host}:${port}`));
process.on('SIGTERM',()=>server.close(()=>process.exit(0)));
}
Starten Sie ihn lokal mit node server.mjs, öffnen Sie http://127.0.0.1:3000 und beenden Sie ihn wieder, bevor Sie fortfahren. Wenn auf Ihrem VPS Port 3000 bereits belegt ist, wählen Sie einen anderen privaten Port und verwenden Sie ihn konsequent im Dienst und im Proxy.
Ersetzen Sie in Ihrem lokalen Projektverzeichnis deploy und VPS_IP durch Ihr SSH-Konto und die tatsächliche Serveradresse:
ssh deploy@VPS_IP 'mkdir -p ~/my-app'
scp index.html server.mjs deploy@VPS_IP:~/my-app/
Installieren Sie diese beiden nicht geheimen Dateien auf dem Server in ein lesbares Anwendungsverzeichnis:
sudo install -d -m 0755 /opt/my-app
sudo install -m 0644 ~/my-app/index.html ~/my-app/server.mjs /opt/my-app/
command -v node
Notieren Sie den absoluten Pfad der Node-Programmdatei. Sie muss außerhalb Ihrer Login-Shell und Ihres Home-Verzeichnisses zugänglich sein. Eine nur für einen Benutzer eingerichtete Installation über einen Versionsmanager unter /home ist für den unten beschriebenen gehärteten Dienst nicht geeignet. Kopieren Sie niemals eine Entwicklungs-.env, einen privaten Schlüssel oder einen Datenbank-Dump in ein öffentliches Webverzeichnis.
3. Die App als systemd-Dienst ohne Root ausführen
Verwenden Sie sudoedit /etc/systemd/system/my-app.service. Ersetzen Sie /ABSOLUTE/PATH/TO/node durch den soeben geprüften, serverweit gültigen Pfad der Programmdatei:
[Unit]
Description=My Node web app
After=network.target
[Service]
Type=simple
DynamicUser=true
WorkingDirectory=/opt/my-app
ExecStart=/ABSOLUTE/PATH/TO/node /opt/my-app/server.mjs
Environment=NODE_ENV=production
Environment=HOST=127.0.0.1
Environment=PORT=3000
Restart=on-failure
RestartSec=2
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
[Install]
WantedBy=multi-user.target
Die Ausführungskontrollen von systemd dokumentieren das dynamische Benutzerkonto und die Härtungseinstellungen. Dieses Profil passt zu unserer schreibgeschützten App; Apps, die Uploads oder Datenbanken schreiben, erfordern bewusst konfigurierten persistenten Speicher und passende Berechtigungen.
sudo systemctl daemon-reload
sudo systemctl enable --now my-app.service
sudo systemctl status my-app.service --no-pager
curl -fsS http://127.0.0.1:3000/
Beheben Sie Anwendungsfehler, bevor Sie DNS anfassen. Ein aktivierter Dienst ist für den Start beim Booten konfiguriert, das ist jedoch kein Nachweis für einen abgeschlossenen Neustarttest.
4. Eine Subdomain auf den VPS zeigen lassen
Erstellen Sie einen A-Record für den gewählten Hostnamen, etwa app.example.com, der auf die öffentliche IPv4-Adresse Ihres VPS zeigt. Bei Cloudflare verwendete unsere Demonstration mit direktem Server die Einstellung Nur DNS und automatische TTL. Übernehmen Sie nicht unsere Demo-IP in die Einträge Ihrer eigenen Website.
Prüfen Sie die öffentliche Antwort mit dig +short A app.example.com. Prüfen Sie auch dig +short AAAA app.example.com: Falls ein IPv6-Eintrag existiert, muss er über IPv6 dieselbe funktionierende Bereitstellung erreichen. DNS ordnet lediglich eine Adresse zu; es startet weder Ihre App noch konfiguriert es HTTPS.
5. Caddy vor die private App schalten
Lassen Sie den Node-Dienst auf 127.0.0.1:3000 laufen. Machen Sie die öffentlichen Webports 80 und 443 über die Firewall des Anbieters und die Host-Firewall erreichbar, ohne Ihren SSH-Zugang zu entfernen. Geben Sie Port 3000 nicht ins Internet frei.
Fügen Sie diesen Site-Block zur Konfiguration Ihres installierten Caddy-Dienstes hinzu und ersetzen Sie den Beispiel-Hostnamen. Behalten Sie nicht zusammenhängende Site-Blöcke bei:
app.example.com {
encode zstd gzip
reverse_proxy 127.0.0.1:3000
}
Die Direktive reverse_proxy leitet öffentliche Anfragen an die private Anwendung weiter. Bei einem geeigneten öffentlichen Hostnamen und funktionierenden Bedingungen für die Zertifikatsvalidierung bezieht und erneuert das automatische HTTPS von Caddy Zertifikate und leitet HTTP auf HTTPS um.
Für den Standard-Caddy-Systemdienst und den Standard-Konfigurationspfad:
sudo caddy validate --config /etc/caddy/Caddyfile --adapter caddyfile
sudo systemctl reload caddy
Unser Film-VPS nutzte einen eigenen Caddy-Dienst und isolierte Konfigurationspfade statt des oben gezeigten gemeinsamen Standarddienstes. Das Routing-Prinzip ist dasselbe; die hier für Leser angegebenen Pfade und Dienstnamen sind Anpassungen und kein wörtliches Installationsprotokoll.
6. Das öffentliche Ergebnis und einen Dienstneustart überprüfen
curl -I http://app.example.com/
curl -I https://app.example.com/
sudo systemctl restart my-app.service
curl --retry 5 --retry-delay 1 --retry-connrefused -I https://app.example.com/
Prüfen Sie auf eine HTTP-Weiterleitung auf HTTPS, eine erfolgreiche HTTPS-Antwort und ein gültiges Zertifikat im Browser. Verwenden Sie nicht curl -k, um Vertrauensfehler zu verdecken. Öffnen Sie die Seite aus einem anderen Netzwerk, nicht nur von innerhalb des VPS.
Eine fehlgeschlagene Neustartprüfung muss untersucht werden: Sehen Sie sich journalctl -u my-app.service -n 50 --no-pager und die Logs des Caddy-Dienstes an. DNS-Fehler, falsches IPv6, eine gestoppte App, ein falscher Upstream-Port und blockierte Zertifikatsvalidierung sind jeweils unterschiedliche Probleme.
Wir haben den Neustart eines Anwendungsdienstes überprüft, nicht den Neustart eines VPS und kein Hochverfügbarkeits-Setup. Planen Sie, bevor Sie eine echte Geschäftsanwendung hosten, auch Updates, Backups, Monitoring, Verwaltung von Geheimnissen und eventuelle persistente Daten ein.
Vom lokalen Projekt zur öffentlichen Adresse
Der gesamte Weg ist unkompliziert: Projekt vorbereiten, auf den VPS übertragen, als verwalteten Dienst ohne Root laufen lassen, DNS auf den Server zeigen lassen und das öffentliche HTTPS am Reverse-Proxy terminieren. Claude Code kann beim Vorbereiten und Erklären dieser Bausteine helfen; Prüfung und betriebliche Kontrollen bleiben dennoch wichtig.
Entdecken Sie die Linux-VPS-Tarife von SharpHeberg, wenn Sie bereit sind, ein lokales Projekt online zu bringen. Das Hosting liefert die Serverumgebung, nicht ein enthaltenes Claude-Abonnement oder ein lokal gehostetes Claude-Modell.