# How to Host a Python Script 24/7 Without a VPS

Running a Python script is easy.

Keeping one running reliably after you close your laptop is where things get more complicated.

Maybe you built a Discord bot. Maybe it’s an automation script that polls an API every few minutes. Maybe it consumes jobs from a queue, processes data in the background, or listens for events.

Locally, you can just run:

```bash
python app.py
```

As long as your terminal stays open and your computer stays awake, everything works.

But that isn’t really deployment.

If the process needs to run continuously, you need somewhere else for it to live. Traditionally, that means renting a VPS, connecting over SSH, installing Python, transferring your code, managing environment variables, configuring a process manager, and figuring out what should happen when the process crashes or the server reboots.

That works. But for a small Python project, it can be a surprising amount of infrastructure to maintain.

There’s another way to think about it.

## A Python script doesn't need to be a website

One reason hosting Python scripts can feel awkward is that many deployment tutorials assume you're building a web application.

They expect something like Flask, Django, or FastAPI to start an HTTP server and listen on a port.

But plenty of useful Python programs don't do that.

Consider a simple worker:

```python
import time

while True:
    print("Checking for work...")

    # Poll an API, process a queue,
    # perform an automation task, etc.

    time.sleep(60)
```

There is no homepage.

There is no HTTP server.

There may not even be a port.

The application is simply a **persistent process**. Its job is to start, keep running, and do something repeatedly.

Discord bots are another good example. So are queue consumers, monitoring processes, scheduled automation loops, data processors, and integrations that maintain long-lived connections.

For these applications, hosting really means giving the process a reliable runtime outside your own computer.

## What “running 24/7” actually requires

Moving a Python script off your laptop solves one problem, but it creates a few others.

A useful deployment environment needs to know:

*   where your code comes from;
    
*   which Python dependencies to install;
    
*   what command starts the program;
    
*   which environment variables it needs;
    
*   where its logs go;
    
*   whether the process is still running;
    
*   and what to do when something fails.
    

That last point is important.

Simply starting a process once doesn't guarantee that it stays online.

Docker, for example, supports restart policies that determine whether a container should be restarted after it exits. Policies such as `on-failure`, `always`, and `unless-stopped` behave differently depending on why the container stopped. ([Docker Documentation](https://docs.docker.com/reference/cli/docker/container/run?utm_source=chatgpt.com))

A deployment platform can take responsibility for more of this lifecycle so you don't have to manually babysit the process.

## Start by making the project deployable

A Python project doesn't need to be complicated to deploy.

A basic repository might look like this:

```text
my-python-worker/
├── app.py
├── requirements.txt
└── README.md
```

Your `requirements.txt` describes the packages the program needs:

```text
requests
discord.py
```

And your application has a clear entry point:

```bash
python app.py
```

The exact structure depends on your project, but the important thing is that another machine should be able to answer two questions:

**What do I install?**

and:

**What do I run?**

If those answers only exist in your head or in the state of your development machine, deployment becomes much harder.

## Put the source code in GitHub

Once the project can be reproduced, GitHub becomes a useful source of truth for the application.

Instead of manually copying files onto a server every time something changes, deployment can begin from a specific revision of the repository.

The basic workflow becomes:

```text
Write code
    ↓
Push to GitHub
    ↓
Select repository
    ↓
Build deployment
    ↓
Start Python process
```

That separation matters.

Your laptop becomes the place where you **develop** the application.

The deployment environment becomes the place where it **runs**.

Closing VS Code, shutting down your PC, or leaving home shouldn't take your production process offline.

## Keep credentials out of the repository

Many long-running Python programs need credentials.

For example:

```python
import os

api_key = os.environ["API_KEY"]
```

You might have:

```text
DISCORD_TOKEN
API_KEY
DATABASE_URL
WEBHOOK_SECRET
```

Those values should not be hardcoded into your source code.

GitHub specifically recommends against hardcoding secrets and recommends environment variables or appropriate secret-management systems instead. Credentials committed to a repository can remain in Git history even after they're removed from the current version of a file. ([GitHub Docs](https://docs.github.com/en/get-started/learning-to-code/storing-your-secrets-safely?utm_source=chatgpt.com))

So instead of doing this:

```python
TOKEN = "my-real-secret-token"
```

your application should expect the deployment environment to provide it:

```python
import os

TOKEN = os.environ["DISCORD_TOKEN"]
```

Then configure `DISCORD_TOKEN` in the environment where the application actually runs.

That also lets development and production use different credentials without changing the source code.

## The VPS approach

You can absolutely host this yourself.

A typical VPS workflow might involve:

```text
Rent VPS
    ↓
SSH into server
    ↓
Install Python
    ↓
Clone repository
    ↓
Install dependencies
    ↓
Configure environment
    ↓
Start process
    ↓
Configure process supervision
    ↓
Monitor logs
```

For developers who want full control of their infrastructure, that's a perfectly reasonable approach.

The tradeoff is ownership.

You now own the server configuration as well as the application.

If the process dies, you need a restart strategy. If the machine reboots, you need the application to return. If a dependency installation fails, you need to diagnose it. If you want to deploy a new revision, you need a repeatable update process.

None of these problems are impossible.

They're just infrastructure problems rather than Python problems.

## The managed approach

If you don't want the server itself to become another project, you can use a deployment platform to manage that layer.

This is the approach we're building with Deploy Hatch.

Instead of provisioning a VPS and configuring it over SSH, the workflow starts with the GitHub repository:

```text
GitHub repository
        ↓
   Deployment
        ↓
 Install dependencies
        ↓
 Build runtime
        ↓
 Start container
        ↓
 Run Python process
        ↓
 Logs + runtime controls
```

The important distinction is that a Python worker doesn't have to pretend to be a website.

If the application is supposed to run:

```bash
python app.py
```

and remain alive, that's the workload.

There doesn't need to be an HTTP endpoint just to satisfy the hosting environment.

## Deploying the Python script

For a repository that's ready to run, the deployment process is fairly small.

Connect the GitHub repository to Deploy Hatch and create a project from it.

The platform can then prepare the runtime, install the application's dependencies, and start the configured Python process inside a container.

Environment variables needed by the application are configured separately rather than committed into the repository.

Once deployment begins, the logs become particularly important.

You want to see whether dependencies installed correctly, whether the application actually started, and what happened if it exited.

A successful build doesn't necessarily mean a successful application.

The real goal is a **running process**.

## Logs are part of the deployment experience

Imagine the application immediately exits with:

```text
KeyError: 'DISCORD_TOKEN'
```

That's very different from an infrastructure failure.

The container may have been created successfully. Python may have installed correctly. Dependencies may be present.

The application itself is telling you that a required environment variable is missing.

Or perhaps you see:

```text
ModuleNotFoundError: No module named 'requests'
```

Now `requirements.txt` is probably the first place to investigate.

Good deployment tooling shouldn't hide these distinctions.

Logs are how you determine whether you're dealing with a build problem, configuration problem, application crash, or platform problem.

## Updating the script

Once GitHub is the source of the deployment, updates become much cleaner.

Make the change locally:

```bash
git add .
git commit -m "Improve worker retry handling"
git push
```

Then deploy the new revision.

That gives you a much more useful mental model than editing files directly on a production server:

```text
Git revision
      ↓
Deployment
      ↓
Running workload
```

You know which version of the code is supposed to be running.

And when something breaks, you have an actual revision to investigate.

## Common reasons Python deployments fail

Most failures aren't particularly exotic.

### Missing dependencies

If your code imports a package, make sure it's actually included in your dependency configuration.

Something working inside your local virtual environment doesn't mean a fresh deployment environment knows about it.

### Missing environment variables

If your program expects:

```python
os.environ["API_KEY"]
```

then `API_KEY` needs to exist in the deployed environment.

### Incorrect start command

Make sure the deployment is starting the correct file.

Your application might use:

```bash
python bot.py
```

rather than:

```bash
python app.py
```

### The program exits normally

Sometimes nothing technically crashes.

The script simply finishes.

For a persistent worker, that means there is no longer a process to keep alive.

A program intended to run continuously needs an execution model that actually remains active, whether that's a loop, queue consumer, persistent connection, scheduler, or another long-running mechanism.

### Secrets committed to Git

Don't treat deleting the credential from the latest commit as sufficient.

GitHub warns that committed credentials can remain in repository history. If a real credential has been exposed, revoke or rotate it rather than assuming deletion made it safe again. ([GitHub Docs](https://docs.github.com/en/code-security/concepts/secret-security/secret-leakage-risks?utm_source=chatgpt.com))

## When should you use a VPS instead?

Managed deployment isn't automatically the right answer for everything.

A VPS may make more sense when you need unusual system packages, low-level operating-system control, custom networking, specialized services, or complete control over the host.

But if your actual goal is:

> “I wrote this Python program and I need it to stay running.”

then it's worth asking whether you really want to become responsible for an entire server just to accomplish that.

For many bots, automation tools, workers, integrations, and small services, the infrastructure is supporting work rather than the product itself.

## Deployment should be boring

A long-running Python script ultimately needs a surprisingly small set of things.

It needs its code.

It needs its dependencies.

It needs its configuration.

It needs somewhere reliable to run.

And when something goes wrong, you need enough visibility to understand why.

Whether you accomplish that with a VPS, Docker on your own infrastructure, or a managed deployment platform is an engineering choice.

But “running Python 24/7” doesn't have to mean leaving a terminal open—or spending your afternoon configuring a Linux server.

If you'd rather deploy from GitHub and let the deployment layer handle the runtime, you can learn more in the Deploy Hatch Python deployment guide.
