Running a trading bot on a laptop is convenient during development. You can edit the strategy, restart the script, inspect logs, and test API integrations directly from your local environment.
The problem begins when the bot needs to operate continuously.
A laptop can go to sleep. Wi-Fi can disconnect. An operating system update can restart the machine. The terminal window can be closed accidentally. Power can fail. Even a stable home connection was not designed to act as production infrastructure for an automated service that may need to remain online around the clock.
Moving the trading bot to a VPS solves many of these problems.
A virtual private server runs independently in a data center and remains available even when your laptop is turned off. Once configured correctly, the bot can start automatically after a reboot, write centralized logs, recover from crashes, and maintain a stable public IP address for exchange API allowlists.
The migration, however, involves more than copying a Python file to another computer.
A production trading bot may depend on Python packages, configuration files, API credentials, local databases, cached market data, open position state, scheduler settings, filesystem paths, and operating system behavior.
This guide explains how to move an existing Python trading bot from a laptop to an Ubuntu VPS safely. We will prepare the local project, deploy a Serverspace VPS, transfer the application, recreate the Python environment, migrate state, configure secrets, test the bot, create a systemd service, configure logging and security, and perform the final cutover without accidentally running two copies of the bot at the same time.
Laptop
VPS
Laptop
State
Laptop
VPS
The final architecture will look approximately like this:
Laptop
Ubuntu VPS
Important: this guide focuses on infrastructure and application migration. Always test the migrated bot with paper trading, an exchange sandbox, or a non-trading mode before enabling real order execution.
Run Your Trading Bot 24/7 on a Serverspace VPS
A trading bot does not need a powerful workstation to remain online.
For many Python trading systems, the more important requirements are stable connectivity, sufficient RAM, reliable storage, a persistent public IP address, and the ability to recover automatically after a process or server restart.
With Serverspace cloud servers, you can deploy an Ubuntu VPS and configure CPU, RAM, SSD capacity, and bandwidth around the requirements of your bot.
This makes a VPS suitable for:
- cryptocurrency trading bots;
- algorithmic trading systems;
- market monitoring applications;
- arbitrage bots;
- price alert services;
- automated portfolio tools;
- exchange API integrations;
- backtesting or data collection services.
Serverspace uses pay-as-you-go billing, so infrastructure can be scaled as the workload changes.
Create a Serverspace VPS and move the execution layer of your trading application away from your personal computer.
What Actually Changes When You Move a Bot to a VPS?
Moving a trading bot is not the same as moving a normal document folder.
The laptop currently provides several layers at once:
- operating system;
- Python runtime;
- installed packages;
- application code;
- API credentials;
- configuration;
- persistent files;
- network connection;
- process management;
- logs.
The VPS needs to recreate all of the layers that the application actually depends on.
A simplified migration looks like this:
The important distinction is that the virtual environment itself should normally not be copied.
Python environments contain absolute paths and platform-specific files. A virtual environment created on Windows or macOS is not a portable Linux environment.
Instead, move the project definition and recreate the environment on the VPS.
Before Migration: Identify Everything the Bot Depends On
Do not start by copying files.
Start by creating an inventory.
Ask these questions:
- Which Python version does the bot use?
- Is the bot already inside a virtual environment?
- Where are the dependencies recorded?
- Does the project use requirements.txt, Poetry, Pipenv, or another dependency manager?
- Where are API keys stored?
- Does the bot write SQLite databases?
- Does it save JSON, CSV, pickle, or cache files?
- Does it remember open positions locally?
- Does it use absolute filesystem paths?
- Does it depend on Windows-specific libraries?
- Does it use a browser or graphical interface?
- Does the exchange restrict API access by IP address?
- Does the bot have Telegram, Discord, email, or webhook integrations?
This inventory determines what must actually move.
Step 1. Record the Current Python Environment
Open a terminal on the laptop inside the working project.
Check the Python version:
python --versionOn some systems:
python3 --versionThen check where Python is running from.
On Linux or macOS:
which python
which python3On Windows PowerShell:
Get-Command pythonIf the project already uses a virtual environment, activate it before exporting dependencies.
Then create a dependency file:
pip freeze > requirements.txtInspect it:
cat requirements.txtOn Windows:
Get-Content requirements.txtThe file may contain entries similar to:
ccxt==4.5.16
pandas==2.3.2
numpy==2.3.3
python-dotenv==1.1.1
requests==2.32.5Your actual dependencies will be different.
The goal is not to reproduce the entire laptop.
The goal is to make the application environment reproducible.
Export Dependencies
Transfer Project
Create New .venv on VPS
Step 2. Separate Code, Configuration, Secrets, and State
One of the most useful improvements during migration is separating the application into four categories.
| Category | Examples | Migration Method |
|---|---|---|
| Code | Python files, strategy modules, utility functions | Git, rsync, SCP |
| Configuration | Trading pair, interval, risk settings, environment mode | Configuration file or environment variables |
| Secrets | API key, API secret, Telegram token | Protected environment file |
| State | SQLite DB, last candle, order IDs, position cache | Controlled final synchronization |
A project directory might eventually look like:
trading-bot/
├── main.py
├── strategy/
├── exchange/
├── config/
├── data/
├── logs/
├── requirements.txt
└── .gitignoreSecrets should not be stored in the Git repository.
Step 3. Identify Persistent State Before You Shut Down the Laptop
This step is easy to overlook and can be more important than the code itself.
Some bots are stateless. They query the exchange every time they start and rebuild their internal state.
Others store information locally.
Examples include:
- last processed market candle;
- last signal timestamp;
- open order identifiers;
- position information;
- trade history;
- cooldown timers;
- SQLite databases;
- CSV files;
- cached indicators;
- local strategy state.
Find these files before migration.
For example:
find . -type f \(-name "*.db" -o -name "*.sqlite" -o -name "*.json" -o -name "*.csv"\)If the bot runs on Windows, inspect the project folder manually or use PowerShell:
Get-ChildItem -Recurse -Include *.db,*.sqlite,*.json,*.csvMake a backup before modifying anything.
Step 4. Check the Bot for Laptop-Specific Assumptions
A project that works on Windows or macOS may fail on Ubuntu even when the Python code is correct.
Look for operating system assumptions.
Filesystem Paths
This path is Windows-specific:
C:\Users\User\TradingBot\data\state.jsonA Linux application should preferably use relative or dynamically constructed paths.
For example:
from pathlib import Path
BASE_DIR = Path(**file**).resolve().parent
STATE_FILE = BASE_DIR / "data" / "state.json"
GUI Dependencies
A VPS normally does not have a desktop environment.
If the bot depends on:
- a visible Chrome window;
- desktop automation;
- Excel GUI integration;
- Windows-only applications;
- local notification popups;
you may need to redesign that component before migration.
Browser automation can often run in headless mode.
Windows-Only Packages
Inspect requirements.txt for packages that depend on Windows.
If installation fails later on Ubuntu, determine whether the dependency has a Linux alternative.
Local Time
Trading logic should ideally work with explicit timestamps rather than assuming that the system clock uses the same local timezone as the laptop.
UTC is generally convenient for server-side market applications.
Step 5. Create a Serverspace VPS
Open the Serverspace control panel.
Select:
For a lightweight Python trading bot, a practical starting configuration can be:
| Resource | Starting Point | When to Increase It |
|---|---|---|
| CPU | 1–2 vCPU | Heavy indicators, many symbols, local analytics |
| RAM | 2 GB | Large pandas DataFrames, multiple workers, databases |
| Storage | 25–40 GB SSD | Historical market data or large logs |
| OS | Ubuntu Server LTS | Change only if the application requires another OS |
| Authentication | SSH key | SSH key should remain the preferred method |
Choose a data center based primarily on network requirements.
For API-based trading, physical distance to the exchange endpoint can influence latency, but it is not the only factor. Network routing and exchange infrastructure also matter.
Do not select a VPS exclusively based on theoretical geographic distance without measuring actual API latency.
Step 6. Connect to the VPS
After the server is created, note its public IP address.
Connect from Linux, macOS, Windows Terminal, or PowerShell:
ssh root@SERVER_IPIf you authenticate using a specific private key:
ssh -i ~/.ssh/trading_vps root@SERVER_IPVerify that you are connected to the expected server:
hostname
hostname -I
uname -aStep 7. Update Ubuntu
Install current package updates:
apt update
apt upgrade -yReboot if required:
rebootConnect again after the server becomes available.
Step 8. Configure the Server Time
Correct time synchronization is particularly important for trading APIs.
Many exchanges reject authenticated requests when the timestamp differs too much from the server time.
Check the current configuration:
timedatectl statusSet UTC:
sudo timedatectl set-timezone UTCEnable network time synchronization:
sudo timedatectl set-ntp trueCheck again:
timedatectl statusThe architecture becomes:
Step 9. Create an Administrative User
Running routine administration as root is unnecessary.
Create a user:
adduser deployAllow sudo access:
usermod -aG sudo deployCopy the SSH directory if the root account already contains your authorized key:
rsync --archive --chown=deploy:deploy ~/.ssh /home/deployOpen another terminal and verify that the new account works:
ssh deploy@SERVER_IPKeep the original session open until you confirm successful access.
Step 10. Configure a Basic Firewall
A normal trading bot generally initiates outbound connections to an exchange.
It usually does not need to accept arbitrary inbound traffic from the Internet.
Enable a basic UFW policy:
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow OpenSSH
sudo ufw enableCheck the rules:
sudo ufw status verboseThe resulting network model is simple:
Firewall
If the application receives webhooks, you may later need to expose HTTPS through a web server or application gateway.
Do not open unnecessary ports.
Step 11. Install Python and Required System Packages
Install Python, pip, virtual environment support, Git, and several common build dependencies:
sudo apt update
sudo apt install -y python3 python3-pip python3-venv git build-essentialCheck Python:
python3 --versionIf the bot was developed against a specific Python version, make sure that version is compatible before continuing.
A migration is not the best time to upgrade both the operating system and the application runtime simultaneously unless you have already tested the combination.
Step 12. Create a Dedicated Service Account
The trading process should not need root privileges.
Create a system account:
sudo adduser --system --group --home /opt/trading-bot tradingbotCreate the application directories:
sudo mkdir -p /opt/trading-bot
sudo mkdir -p /opt/trading-bot/data
sudo mkdir -p /opt/trading-bot/logsAssign ownership:
sudo chown -R tradingbot:tradingbot /opt/trading-botThe privilege model becomes:
root
tradingbot
This limits the impact of an application-level compromise.
Step 13. Transfer the Bot to the VPS
There are several reasonable approaches.
Option A. Git
If the project is stored in a private Git repository, Git is usually the cleanest deployment method.
Clone into a temporary directory:
cd /tmp
git clone REPOSITORY_URL trading-botThen copy the files:
sudo rsync -av --exclude=".git" /tmp/trading-bot/ /opt/trading-bot/
sudo chown -R tradingbot:tradingbot /opt/trading-botDo not store exchange API credentials in the repository.
Option B. rsync
From a Linux or macOS laptop:
rsync -avz
--exclude=".venv"
--exclude="venv"
--exclude=".git"
--exclude="**pycache**"
./ deploy@SERVER_IP:/tmp/trading-bot/Then on the VPS:
sudo rsync -av /tmp/trading-bot/ /opt/trading-bot/
sudo chown -R tradingbot:tradingbot /opt/trading-botOption C. SCP
For a simple project:
scp -r ./trading-bot deploy@SERVER_IP:/tmp/Windows PowerShell can use the same OpenSSH SCP client:
scp -r .\trading-bot deploy@SERVER_IP:/tmp/Then move the project into place.
What Should Not Be Copied?
Avoid blindly transferring:
- .venv;
- venv;
- __pycache__;
- local IDE configuration;
- temporary files;
- large development datasets that production does not need;
- old logs;
- credentials stored in development files.
A useful .gitignore might include:
.venv/
venv/
**pycache**/
*.pyc
.env
logs/
.DS_Store
.vscode/
.idea/Do not ignore persistent production state if that state needs to be deliberately backed up and restored. Treat it separately instead.
Step 14. Recreate the Python Virtual Environment
Switch to the project directory:
cd /opt/trading-botCreate a new environment:
sudo -u tradingbot python3 -m venv /opt/trading-bot/.venvUpgrade pip:
sudo -u tradingbot /opt/trading-bot/.venv/bin/python -m pip install --upgrade pipInstall dependencies:
sudo -u tradingbot /opt/trading-bot/.venv/bin/pip install -r /opt/trading-bot/requirements.txtVerify installed packages:
sudo -u tradingbot /opt/trading-bot/.venv/bin/pip listThe important difference is:
Laptop .venv
requirements.txt
Step 15. Fix Dependency Problems Before Migrating Real State
If pip fails, stop here.
Do not copy production state and API credentials until the software environment works.
Common issues include:
- package has no Linux build;
- package requires a system library;
- Python version differs;
- dependency version is outdated;
- Windows-specific package was frozen into requirements.txt;
- package requires compilation.
Inspect the error and install required Ubuntu libraries where necessary.
For example, some database or scientific Python packages may require additional development headers.
The exact dependencies depend on the bot.
Step 16. Store API Keys Outside the Source Code
Do not hardcode a production exchange key inside main.py.
A cleaner architecture is:
Create a protected environment file:
sudo nano /etc/trading-bot.envExample:
EXCHANGE_API_KEY=YOUR_API_KEY
EXCHANGE_API_SECRET=YOUR_API_SECRET
TRADING_MODE=paper
TRADING_PAIR=BTC_USDTProtect the file:
sudo chown root:tradingbot /etc/trading-bot.env
sudo chmod 640 /etc/trading-bot.envVerify:
sudo ls -l /etc/trading-bot.envDo not copy the file into a public repository.
Reduce API Key Permissions
Before the final migration, review the exchange or broker permissions assigned to the API key.
Where supported:
- enable only the permissions the bot actually needs;
- disable withdrawals;
- disable administrative permissions;
- use a dedicated API key for the bot;
- apply a VPS IP allowlist;
- rotate old credentials if they were previously stored insecurely.
A production key should follow the principle of least privilege.
Step 17. Test the Application Without Real Trading
Before migrating live execution, make sure the application starts successfully on the VPS.
Run the bot as the service account.
If the application loads configuration directly from a .env file inside the project, use the relevant test setup.
For a simple manual test:
sudo -u tradingbot /opt/trading-bot/.venv/bin/python /opt/trading-bot/main.pyThe bot should:
- start without import errors;
- connect to the required market data API;
- load configuration;
- read required files;
- write to the correct data directory;
- handle timestamps correctly;
- produce logs.
Use a sandbox, paper-trading mode, read-only key, or disabled order execution during this test.
Step 18. Test Exchange Connectivity from the VPS
A working Internet connection does not automatically guarantee that the exchange endpoint is reachable.
Test DNS:
getent hosts EXCHANGE_API_HOSTTest HTTPS connectivity:
curl -I https://EXCHANGE_API_HOSTMeasure basic connection timing:
curl -o /dev/null -s -w "connect=%{time_connect} total=%{time_total}\n" https://EXCHANGE_API_HOSTRepeat the test several times rather than making a decision from one measurement.
If the exchange supports API IP allowlisting, add the VPS public IP before enabling the production key.
Check the VPS IP:
curl https://api.ipify.org
echoStep 19. Migrate Persistent State
Do not perform the final state migration while the laptop bot continues modifying the same files.
The safest pattern is:
For example, if state is stored in a directory named data:
rsync -avz ./data/ deploy@SERVER_IP:/tmp/trading-state/Then on the VPS:
sudo rsync -av /tmp/trading-state/ /opt/trading-bot/data/
sudo chown -R tradingbot:tradingbot /opt/trading-bot/dataFor SQLite, make sure the database is not being written during a raw file copy.
A safer application-level SQLite backup can be created with:
sqlite3 bot.db ".backup bot-backup.db"Then transfer bot-backup.db.
The Most Important Migration Rule: Never Run Two Live Copies Accidentally
This is especially important for automated trading systems.
If the laptop bot and VPS bot both use the same API credentials and strategy state, they may both react to the same signal.
That can result in:
- duplicate orders;
- double position sizing;
- conflicting stop orders;
- incorrect state synchronization;
- race conditions;
- duplicate notifications.
During final cutover, there should be one clear execution owner.
Do not use the laptop as an automatic backup bot unless the application was explicitly designed for active-passive failover.
Step 20. Create a systemd Service
Manual execution through SSH is not suitable for production.
If the SSH connection closes, a foreground process may terminate. More importantly, the application will not automatically recover after a reboot.
systemd solves this problem.
Create a service:
sudo nano /etc/systemd/system/trading-bot.serviceAdd:
[Unit]
Description=Python Trading Bot
After=network-online.target
Wants=network-online.target
StartLimitIntervalSec=300
StartLimitBurst=5
[Service]
Type=simple
User=tradingbot
Group=tradingbot
WorkingDirectory=/opt/trading-bot
EnvironmentFile=/etc/trading-bot.env
Environment=PYTHONUNBUFFERED=1
ExecStart=/opt/trading-bot/.venv/bin/python /opt/trading-bot/main.py
Restart=on-failure
RestartSec=10
TimeoutStopSec=30
KillSignal=SIGINT
NoNewPrivileges=true
PrivateTmp=true
[Install]
WantedBy=multi-user.target
Reload systemd:
sudo systemctl daemon-reloadEnable automatic startup:
sudo systemctl enable trading-botStart the service:
sudo systemctl start trading-botCheck it:
sudo systemctl status trading-botThe execution model becomes:
Process Healthy
Process Crashes
Why Restart=on-failure Is Usually Better Than an Infinite Restart Loop
A bot should recover from temporary failures, but automatic restarting can also hide a serious application problem.
For example:
- invalid API credentials;
- corrupted state database;
- missing configuration;
- broken deployment;
- unsupported dependency update.
The StartLimit settings prevent systemd from restarting a completely broken application indefinitely in a tight loop.
Application-level alerts should still notify you when repeated failures occur.
Step 21. Read Trading Bot Logs
systemd automatically sends stdout and stderr to the journal.
View recent logs:
sudo journalctl -u trading-botFollow logs in real time:
sudo journalctl -u trading-bot -fShow logs from the last hour:
sudo journalctl -u trading-bot --since "1 hour ago"Show logs from the current boot:
sudo journalctl -u trading-bot -bThe logging path is now:
If the bot also writes its own log files, configure rotation so they cannot consume the complete VPS disk.
Step 22. Configure Log Rotation for Application Files
Suppose the bot writes:
/opt/trading-bot/logs/bot.logCreate:
sudo nano /etc/logrotate.d/trading-botExample:
/opt/trading-bot/logs/*.log {
daily
rotate 14
compress
missingok
notifempty
copytruncate
}Test the configuration:
sudo logrotate -d /etc/logrotate.d/trading-botLarge unrotated log files are a common source of avoidable production outages.
Step 23. Monitor VPS Resource Usage
A bot that uses little CPU during development can still accumulate memory, data, or logs over time.
Check memory:
free -hCheck disk:
df -hCheck load:
uptimeInspect processes:
topOr install htop:
sudo apt install -y htop
htopWatch the actual Python process:
ps aux | grep main.pyLook for:
- steadily increasing RAM consumption;
- high CPU utilization;
- disk usage growth;
- rapid log generation;
- unexpected restart frequency.
Step 24. Add Application Health Checks
A running process does not necessarily mean a healthy bot.
The application can remain alive while:
- WebSocket data has stopped;
- API authentication is failing;
- market data is stale;
- an internal worker has crashed;
- no new candles are processed;
- the application is stuck waiting forever.
A production bot should ideally expose or record health indicators such as:
- last successful API request;
- last received market update;
- last processed strategy cycle;
- last order synchronization;
- current process uptime;
- current trading mode.
A simple status file could contain:
{
"status": "ok",
"mode": "paper",
"last_market_update": "2026-09-04T11:42:18Z",
"last_strategy_cycle": "2026-09-04T11:42:20Z"
}Monitoring software can then alert when timestamps become stale.
Step 25. Send Failure Notifications Somewhere Other Than the VPS
Logs stored only on the server are useful after you notice a problem.
They do not notify you that the problem exists.
A production bot can send external alerts through:
- Telegram;
- Discord;
- email;
- Slack;
- a monitoring service;
- a dedicated webhook endpoint.
Useful alerts include:
- bot started;
- bot stopped;
- API authorization failed;
- market data became stale;
- order submission failed;
- repeated process restart detected;
- disk usage exceeded a threshold;
- unexpected exception occurred.
The monitoring architecture becomes:
External Notification
Step 26. Configure Backups
A VPS removes dependence on the laptop, but it does not remove the need for backups.
Important data can include:
- bot source code;
- configuration;
- SQLite databases;
- trade state;
- historical market data;
- custom strategy files;
- application settings.
The code should preferably already exist in version control.
Persistent state needs a separate backup strategy.
Serverspace provides a backup service for virtual machines. Server backups can be created automatically and stored independently from the active VM.
A sensible model is:
Git Repository
Application Backup
VPS Backup
Do not treat one backup mechanism as the only copy of important trading records.
Step 27. Perform the Final Production Cutover
By this point:
- the VPS exists;
- Python dependencies are installed;
- the code runs;
- network connectivity works;
- secrets are configured;
- systemd is ready;
- logging works;
- the bot has passed paper or sandbox testing.
Now perform the final migration.
1. Disable Automatic Startup on the Laptop
Remove any scheduled task, startup shortcut, Docker restart policy, or local service that could automatically restart the old bot.
2. Stop the Laptop Bot
Verify that no copy remains running.
On Linux or macOS:
ps aux | grep main.pyOn Windows PowerShell:
Get-Process python*3. Create the Final State Backup
Back up any mutable application state.
4. Synchronize the Final State
Transfer the final database or state files to the VPS.
5. Verify Permissions
sudo chown -R tradingbot:tradingbot /opt/trading-bot/data6. Update the Exchange IP Allowlist
If the exchange uses IP restrictions, authorize the VPS address.
Remove the old laptop or home IP if it is no longer required.
7. Enable Production Mode
Edit:
sudo nano /etc/trading-bot.envChange the application-specific setting only after all previous checks are complete.
For example:
TRADING_MODE=live8. Restart the Service
sudo systemctl restart trading-bot9. Watch the Logs
sudo journalctl -u trading-bot -fConfirm:
- API authentication;
- market data flow;
- position synchronization;
- state loading;
- correct trading pair;
- correct strategy configuration;
- expected balance data;
- no duplicate process.
Step 28. Verify That Only One Bot Instance Is Running
Check systemd:
sudo systemctl status trading-botCheck Python processes:
pgrep -af pythonYou should understand every relevant process shown.
If a second manual test process is still running, terminate it before enabling production trading.
This check should become part of every future deployment.
Step 29. Test VPS Reboot Recovery
The migration is not complete until you know the bot can survive a server restart.
First confirm that systemd is enabled:
sudo systemctl is-enabled trading-botExpected:
enabledThen reboot during a safe maintenance window:
sudo rebootReconnect:
ssh deploy@SERVER_IPCheck:
sudo systemctl status trading-botThen inspect boot logs:
sudo journalctl -u trading-bot -bThe bot should have started automatically.
Step 30. Create a Repeatable Deployment Process
Do not repeat the complete migration every time you change one strategy file.
After the first migration, updates should follow a controlled deployment flow.
A simple Git-based workflow can be:
A basic manual update can look like:
sudo systemctl stop trading-bot
cd /opt/trading-bot
git pull
/opt/trading-bot/.venv/bin/pip install -r requirements.txt
sudo systemctl start trading-bot
sudo systemctl status trading-bot
If /opt/trading-bot is managed directly as a Git working tree, configure ownership and repository permissions appropriately for the deployment model.
For larger projects, CI/CD should eventually replace manual production updates.
Build a Safer Deployment with Releases and Rollback
Updating files directly in the active directory is simple but makes rollback harder.
A more mature directory structure is:
/opt/trading-bot/
releases/
20260918-0930/
shared/
current
releases/20260918-0930/
systemd can execute:
/opt/trading-bot/current/.venv/bin/pythonIf a release fails, switch the current symlink back to the previous release.
The deployment architecture becomes:
What Should Stay on the Laptop After Migration?
The laptop still has an important role.
It becomes the development environment rather than the execution environment.
A clean division is:
| Laptop | VPS |
|---|---|
| Write code | Run production code |
| Backtest strategies | Process live market data |
| Run unit tests | Run continuously |
| Commit changes | Pull approved releases |
| Paper trading | Production execution |
That separation also reduces the chance that unfinished development code accidentally affects live execution.
Recommended Trading Bot Production Architecture
After migration, the complete infrastructure can look like this:
Serverspace Ubuntu VPS
Exchange API
External Monitoring
Common Migration Problems
ModuleNotFoundError
Example:
ModuleNotFoundError: No module named "ccxt"Make sure the application is using the VPS virtual environment:
/opt/trading-bot/.venv/bin/python -m pip listInstall requirements again if necessary.
Permission Denied
Check ownership:
ls -la /opt/trading-botRestore application ownership:
sudo chown -R tradingbot:tradingbot /opt/trading-botDo not give the entire project 777 permissions.
API Authentication Fails Only on VPS
Check:
- API key and secret;
- environment variables;
- VPS clock;
- exchange IP allowlist;
- API permissions;
- network availability.
Bot Works Manually but Fails Under systemd
The most common difference is the environment.
systemd does not automatically load your interactive shell configuration.
Use explicit values for:
- WorkingDirectory;
- EnvironmentFile;
- Python interpreter path;
- application path.
Inspect service logs:
sudo journalctl -u trading-bot -n 100Bot Stops When SSH Disconnects
The application is probably still being started manually.
Run it as a systemd service instead.
Bot Starts Twice
Check:
pgrep -af pythonMake sure you do not simultaneously use:
- systemd;
- cron;
- screen;
- tmux;
- Docker restart;
- manual execution.
Only one process manager should own the production bot unless the software was designed for distributed execution.
Disk Space Keeps Falling
Check:
df -hFind large directories:
sudo du -h /opt/trading-bot | sort -h | tailInspect journal size:
journalctl --disk-usageLogs and historical market data are common causes.
Production Migration Checklist
Before declaring the move complete, verify:
- the project is backed up;
- requirements.txt is reproducible;
- Python version is compatible;
- the VPS uses a supported Ubuntu LTS release;
- SSH key authentication works;
- only required firewall ports are open;
- the application runs under a non-root account;
- API credentials are outside the repository;
- withdrawal permissions are disabled where possible;
- VPS IP restrictions are configured where supported;
- persistent state was migrated after stopping the old bot;
- the laptop copy cannot automatically restart;
- only one production bot process exists;
- systemd starts the bot;
- systemd automatically starts after reboot;
- logs are accessible;
- log files are rotated;
- external alerts work;
- VPS resource usage is monitored;
- backups are configured;
- rollback is possible;
- the bot was tested without real orders before production cutover.
Moving from a Laptop to a VPS Changes More Than Uptime
The obvious benefit of a VPS is that the bot can continue running when the laptop is offline.
The more important improvement is architectural.
Before migration:
Laptop
Development
Secrets
State
Runtime
Logs
Production Execution
Everything exists inside one personal machine.
After migration:
Laptop
Development
Testing
Git / Deployment
Serverspace VPS
Production Runtime
systemd
Protected Secrets
Persistent State
Logging
Monitoring
Backups
Exchange API
This separation makes the application easier to operate, update, recover, and eventually automate.
Next Step: Build the Bot Directly on an Ubuntu VPS
If you do not already have a working trading bot, Serverspace also has a separate guide explaining how to deploy a Python trading bot on Ubuntu VPS from the beginning.
The two workflows solve different problems:
- new deployment — create the environment and bot directly on the VPS;
- migration — move an existing working bot without losing dependencies, state, configuration, or control over production execution.
Run Your Trading Bot on Serverspace
A VPS turns the trading bot from a process attached to a personal computer into an independent service.
With Serverspace VPS, you can deploy an Ubuntu server, select the required CPU, RAM, SSD, and network resources, and manage the infrastructure through a web control panel.
The bot can then operate with:
- continuous server availability;
- a persistent execution environment;
- SSH administration;
- automatic systemd startup;
- server-side logging;
- backup options;
- scalable resources;
- a stable public IP for supported exchange allowlists.
Start with a small configuration and monitor actual CPU, memory, storage, and network consumption. Resources can be adjusted later when the trading workload grows.
Create a cloud server in Serverspace and move your trading bot from a personal laptop to an always-on production environment.
Trading Bot VPS Migration FAQ
Why should I move a trading bot from my laptop to a VPS?
A VPS can remain online independently from your personal computer, Internet connection, battery, sleep settings, and local operating system. It also provides a stable execution environment where the trading bot can start automatically, run under systemd, store centralized logs, and use a persistent public IP address.
Can I copy my Python virtual environment from my laptop to a VPS?
Usually no. Python virtual environments are not designed to be portable between operating systems or filesystem locations. Transfer the source code and dependency definition instead, create a new virtual environment on the VPS, and install the required packages again using requirements.txt or the dependency manager used by the project.
How much RAM does a Python trading bot need on a VPS?
A lightweight trading bot can often start with around 1–2 GB of RAM, but actual requirements depend on the application. Bots that process many symbols, keep large pandas DataFrames in memory, run multiple workers, maintain databases, or perform local analytics may require additional RAM. Monitor real resource consumption after deployment instead of sizing the VPS only from estimates.
How do I keep a trading bot running after I disconnect from SSH?
Run the application as a systemd service rather than starting it manually in an SSH terminal. systemd can keep the process independent from the SSH session, restart it after failures, and automatically launch the bot after the VPS reboots.
How do I safely move API keys to a VPS?
Do not commit exchange credentials to Git or hardcode them inside the Python source. Store them in a protected environment file readable only by the required system account. Where supported, use a dedicated trading API key, disable withdrawal permissions, apply the VPS public IP allowlist, and grant only the permissions required by the bot.
How can I move a live trading bot without creating duplicate orders?
Prepare and test the VPS first without live execution. During the final cutover, stop the laptop bot completely, create the final state backup, synchronize persistent data to the VPS, confirm that the old process cannot restart automatically, update any API IP restrictions, and only then start one production instance on the VPS. Running both copies simultaneously can cause duplicate signals or orders.