YouTube Converter V1 — VPS Installation Guide
V1 • SELF-HOSTED • VPS

YouTube Converter V1

A complete deployment guide for installing YouTube Converter V1 on a Linux VPS, configuring the media-processing stack, running it as a production service, and optionally exposing it through Nginx and HTTPS.

Node.js v22.23.2 testednpm 10.9.8 testedyt-dlp 2026.07.04 testedFFmpeg 6.1.1 testedUbuntu/Debian workflow

1. Requirements

Recommended VPS

  • Ubuntu 24.04 LTS or current Debian
  • 2 CPU cores minimum
  • 2 GB RAM minimum; 4 GB+ recommended
  • 20 GB+ free disk space
  • Root or sudo access
  • Public IP if internet-facing

V1 tested software

ComponentVersion
Node.jsv22.23.2
npm10.9.8
yt-dlp2026.07.04
FFmpeg6.1.1
FFprobe6.1.1
Compatibility note: yt-dlp and YouTube extraction behaviour can change independently of the application. Always test the yt-dlp version deployed to production.

2. Prepare the VPS

Connect over SSH and update the server:

ssh root@YOUR_SERVER_IP
apt update
apt upgrade -y
apt install -y curl git build-essential ca-certificates python3 python3-venv python3-pip nginx ufw
cat /etc/os-release
uname -a
df -h
Disk space matters. Conversions create temporary and output files. Monitor storage, especially on small VPS plans.

3. Install Node.js

The V1 release was tested with Node.js 22.23.2.

curl -fsSL https://deb.nodesource.com/setup_22.x | bash -
apt install -y nodejs
node --version
npm --version

For the tested environment, the versions were v22.23.2 and 10.9.8. Repository packages can move forward, so pin versions if you need a reproducible environment.

4. Install FFmpeg and FFprobe

apt install -y ffmpeg
command -v ffmpeg
command -v ffprobe
ffmpeg -version | head -1
ffprobe -version | head -1

5. Download the application

cd /opt
git clone git@github.com:Tankonline/youtube-converter-v1.git youtube-converter-v1
cd /opt/youtube-converter-v1
git status
git log --oneline --decorate -3
npm ci
npm list --depth=0

If GitHub SSH authentication is not configured on the VPS, clone the repository using its HTTPS URL instead.

6. Create and configure the application

cd /opt/youtube-converter-v1
cp config/config.example.yml config/config.yml
mkdir -p data temp
chmod 640 config/config.yml

Server

For a reverse-proxy deployment, keep Node private:

server:
host: "127.0.0.1"
port: 3000

Tools

tools:
ytdlp: "./venv/bin/yt-dlp"
ffmpeg: "ffmpeg"
ffprobe: "ffprobe"

Review the conversion limits, queue limits, rate limits, retention settings and branding before exposing the service publicly.

7. Install the tested yt-dlp version

The virtual environment is intentionally created on each VPS; it is not part of the Git repository.

cd /opt/youtube-converter-v1
python3 -m venv venv
./venv/bin/pip install --upgrade pip
./venv/bin/pip install yt-dlp==2026.07.04
./venv/bin/yt-dlp --version

Then ensure config/config.yml contains:

ytdlp: "./venv/bin/yt-dlp"
node -e "const { loadConfig } = require('./config/config'); console.log(loadConfig().tools)"
YouTube extraction can require additional components. If yt-dlp reports a missing JavaScript runtime, bot challenge, login requirement, or unavailable video, diagnose the direct yt-dlp command first. Do not assume the Node application is the cause.

8. Test before production

Validate configuration

node -e "const { loadConfig } = require('./config/config'); console.log(loadConfig())"

Start manually

npm start

From another SSH session:

curl -I http://127.0.0.1:3000/
curl -s http://127.0.0.1:3000/ | grep -o '<title[^>]*>[^<]*</title>'

Test yt-dlp separately

./venv/bin/yt-dlp --verbose --skip-download \
"https://www.youtube.com/watch?v=VIDEO_ID"

Test the API

curl -sS -X POST http://127.0.0.1:3000/api/info \
-H 'Content-Type: application/json' \
--data '{"url":"https://www.youtube.com/watch?v=VIDEO_ID"}'

9. Production systemd service

Use systemd instead of relying on an SSH session or nohup.

useradd --system --home /opt/youtube-converter-v1 --shell /usr/sbin/nologin youtubeconverter || true
chown -R youtubeconverter:youtubeconverter /opt/youtube-converter-v1
nano /etc/systemd/system/youtube-converter.service

Service file:

[Unit]
Description=YouTube Converter V1
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=youtubeconverter
Group=youtubeconverter
WorkingDirectory=/opt/youtube-converter-v1
Environment=NODE_ENV=production
ExecStart=/usr/bin/npm start
Restart=on-failure
RestartSec=5
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=full
ProtectHome=true
[Install]
WantedBy=multi-user.target
systemctl daemon-reload
systemctl enable --now youtube-converter
systemctl status youtube-converter --no-pager
journalctl -u youtube-converter -n 100 --no-pager
Checkpoint: the service should be active and Node should listen on 127.0.0.1:3000.

10. Nginx reverse proxy

Replace converter.example.com with your real domain.

nano /etc/nginx/sites-available/youtube-converter
server {
listen 80;
listen [::]:80;
server_name converter.example.com;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 3600;
proxy_send_timeout 3600;
}
}
ln -s /etc/nginx/sites-available/youtube-converter /etc/nginx/sites-enabled/youtube-converter
nginx -t
systemctl reload nginx

11. HTTPS

Point your DNS A/AAAA records at the VPS first, then:

apt install -y certbot python3-certbot-nginx
certbot --nginx -d converter.example.com
certbot renew --dry-run
DNS first. The domain must resolve to the server before certificate issuance can succeed.

12. Security hardening

Firewall

ufw allow OpenSSH
ufw allow 'Nginx Full'
ufw enable
ufw status verbose
  • Keep Node bound to 127.0.0.1.
  • Do not publicly expose port 3000.
  • Prefer SSH keys over passwords.
  • Keep the OS and application dependencies patched.
  • Run the production service as a dedicated non-root account.
  • Keep runtime data and private configuration out of Git.
  • Monitor disk usage.

13. Updating the deployment

cd /opt/youtube-converter-v1
cp config/config.yml /root/youtube-converter-config.backup.yml
git status
git pull --ff-only
npm ci
./venv/bin/pip install --upgrade yt-dlp
systemctl restart youtube-converter
systemctl status youtube-converter --no-pager
journalctl -u youtube-converter -n 100 --no-pager
Test before upgrading production. New yt-dlp versions can change YouTube extraction behaviour even when the Node application has not changed.

Verify deployed versions

git log --oneline --decorate -5
git status
node --version
npm --version
./venv/bin/yt-dlp --version
ffmpeg -version | head -1
ffprobe -version | head -1

14. Troubleshooting

Service will not start

systemctl status youtube-converter --no-pager
journalctl -u youtube-converter -n 200 --no-pager
cd /opt/youtube-converter-v1
node -e "const { loadConfig } = require('./config/config'); console.log(loadConfig())"

Port conflict

ss -ltnp | grep ':3000'
ps aux | grep '[n]ode.*youtube-converter'

/api/info fails

cd /opt/youtube-converter-v1
./venv/bin/yt-dlp --version
./venv/bin/yt-dlp --verbose --skip-download "https://www.youtube.com/watch?v=VIDEO_ID"

Use the direct yt-dlp error to identify YouTube availability, authentication, bot challenge, JavaScript-runtime, or extractor issues.

Nginx returns 502

systemctl status youtube-converter --no-pager
ss -ltnp | grep ':3000'
curl -I http://127.0.0.1:3000/
nginx -t
journalctl -u nginx -n 100 --no-pager

Storage problems

df -h
du -sh /opt/youtube-converter-v1/temp
du -sh /opt/youtube-converter-v1/data

Permission problems

namei -l /opt/youtube-converter-v1
ls -ld /opt/youtube-converter-v1/data /opt/youtube-converter-v1/temp
ps aux | grep '[n]ode.*server.js'

15. Uninstall

systemctl disable --now youtube-converter
rm -f /etc/systemd/system/youtube-converter.service
systemctl daemon-reload
rm -f /etc/nginx/sites-enabled/youtube-converter
rm -f /etc/nginx/sites-available/youtube-converter
nginx -t
systemctl reload nginx
# Only run after confirming all required data has been backed up:
rm -rf /opt/youtube-converter-v1

16. Final deployment checklist

  • VPS updated and secured
  • Node.js/npm installed
  • FFmpeg/FFprobe installed
  • Repository cloned and npm ci completed
  • config/config.yml created
  • data and temp directories created
  • Python virtual environment created
  • yt-dlp 2026.07.04 installed/tested
  • Local HTTP endpoint returns 200
  • Direct yt-dlp extraction tested
  • systemd service enabled
  • Nginx configured if public
  • HTTPS configured if public
  • Firewall configured
  • Port 3000 remains private
  • Production service runs as non-root
  • Disk and conversion limits reviewed
YouTube Converter V1 — VPS Installation Guide
This guide reflects the V1 deployment structure and the software versions tested for the release. Verify current VPS packages, yt-dlp behaviour, YouTube compatibility, and your chosen Linux distribution before production deployment.
Scroll to Top