3 horizontal lines, burger
3 horizontal lines, burger
3 horizontal lines, burger
3 horizontal lines, burger

3 horizontal lines, burger
Remove all
LOADING ...

Content



    How to deploy a website on timeweb(either hosting or vps). Full insturction

    Clock
    24.07.2025
    /
    Clock
    01.10.2025
    /
    Clock
    27 minutes
    An eye
    1014
    Hearts
    2
    Connected dots
    1
    Connected dots
    0
    Connected dots
    2

    Introduction or what the article is about

    In this article I will tell and show how you can host a site on servers from timeweb (hosting provider). This provider offers a wide range of development platforms/CMS that are used to create a site. But in this article I will only tell you how to deploy a site written in Django, because I understand this.
    In addition to what was said earlier, I also want to show how you can set up your project/site so that if you need to implement new features, or fix them), it is no more difficult than pressing one button. We will do this through bash, git and ssh.
    In addition to providing regular (virtual) hosting, timeweb provides such a service as VPS. So, on timeweb, your site can be hosted in two ways:
    1. Quick and easy, although not without nuances. The point is to use the provided functionality without having to use the terminal. As you will see later, you will still have to use it.
    2. A bit tedious and confusing, but with much more freedom in placement. The essence of the second method is to create your VPS and configure the server manually. (Phusion Passenger/Gunicorn) (Nginx/Apache2)
    VPS(Virtual Private Server) - such a server is located together with others on the same hardware (computer), hence the virtual server, also access to such a server is only available to its owner, hence the private.
    This article is divided into 3 main parts:
    1. The first is Preparation. It needs to be done regardless of which deployment platform you have chosen.
    2. The second is Deployment on a virtual hosting. It will tell you how to deploy a site to a virtual hosting, with minimal interaction with the terminal.
    3. The third is Deployment on a VPS. It will tell you how to create and configure your VPS on timeweb. After which the Django application itself will be deployed.
    I will demonstrate both methods. I will explain the features and nuances of both, and why VPS is better, in my opinion. You can go straight to the comparison here.

    Features of this tutorial

    For demonstration I will use a specially made for this django application. This application was specially made with all the features that your Django site will probably use:
    1. Working and setting up with the database
    2. Working and setting up mail
    3. Working with statics
    4. Working with media files
    5. Working with translations
    6. Testing the application
    I am constantly working on this application, because I am going to test it on other hostings (not only timeweb). In the end, I see it as one big interactive test of hostings, on how friendly they are to Django sites.

    Preparation, or how to buy a domain

    To buy a domain, go to https://hosting.timeweb.ru/domains/registration. There will be a field for entering the desired domain, enter it, register:
    Selecting and registering a domain on timeweb.com
    Afterwards you will be redirected to the domain settings page, there you don't have to take an SSL certificate. A little later, we will install a free one from LetsEncrypt
    Setting up a new domain on timeweb.com
    Now that we have a domain in hand, let's link it to the site and install an SSL certificate. All this can be done on this page: https://hosting.timeweb.ru/domains/settings?fqdn=DOMAIN_NAME
    You only need to bind and install an SSL certificate if you are hosting your site on a virtual hosting. If you decide to deploy your site on a VPS, don't do it.
    Where DOMAIN_NAME is a full name of the newly acquired domain.
    To link a domain to a site, you still need to create it. This can be done on this page https://hosting.timeweb.ru/sites.
    Why bother with an SSL certificate? Won't my site work without it? It will, but users, browsers, and search engines won't trust it, especially if the site is about finance, politics, or other very important topics where the security of requests sent to the server is a priority.
    1. You will need to attach the domain to the created site. After that, you will have to wait from 15 minutes to 24 hours until the DNS is updated.
    2. After clicking, a selection of available SSL certificates will be presented. Choose LetsEncrypt and move on

    Deployment on virtual hosting

    Creating a database

    We already have a website and a website linked to it. Let's add a database to the list of completed tasks. Creating and editing databases is done here -> https://hosting.timeweb.ru/mysql
    Database creation page
    You will need to fill in and then remember the following values:
    1. Database name (cs86772_bd for me, respectively)
    2. Username (will match the database name)
    3. Database password
    Also, if you are going to host the site on a VPS, do not forget to add an additional access address to the database.
    Timeweb for virtual hosting currently provides databases only on MySQL 8

    Creating mail

    Setting up mail is even easier than setting up a database. On the page https://hosting.timeweb.ru/mailman, click on "Add mailbox" and enter the required data. You will need to remember the following data (they will be needed for setting up later):
    What is highlighted in CAPS and bold is the name of the constant that can be applied later in the settings.py file.
    1. some@cs86772.tw1.ru - a login to enter (EMAIL_HOST_USER)
    2. 743Ew0x35 - a password to enter (EMAIL_HOST_PASSWORD)
    1. smtp.timeweb.ru - post server to send the mail (EMAIL_HOST)
    2. 465 - a post to connect to post server (EMAIL_PORT)
    SMTP (Simple Mail Transfer Protocol) - is an electronic standard protocol that enables the transmission of messages between mail servers on the Internet. It enables the sender to receive messages and also enables the forwarding of messages between servers.
    POP3 (Post Office Protocol 3) - It is a protocol used to receive mail from a mail server to a user's device.
    IMAP (Internet Message Access Protocol) - It is a protocol that allows users to access and manage email stored on a remote server using various devices such as computers, tablets or smartphones.

    Connect to a virtual hosting via SSH

    Having finished with the preparatory part, we can proceed directly to the deployment. To be able to work with a remote server, we need to connect to it. There are several ways to do this, the easiest is to use the built-in commands and utilities of the hosting itself.
    And to get access via SSH, you can use the browser terminal from timeweb.
    This is quite important. I don't know why they don't write this, but in order to activate access to the server via SSH, confirmation via a mobile phone is required (RUSSIAN ONLY). Although they offer more options. I am from Belarus, so there was a slight delay (╯_╰). I had to contact the support service, there they activated my account without any problems, so don't be shy, ask.
    Login to the web terminal
    Start page styled with command
    SSH (Secure SHell) - is an Internet protocol that enables secure, encrypted communication between a client and a server. There is an SSH client (it is required for the machines from which the connection will be made), and there is an SSH server (it is required if you want to provide remote access to your machine). All servers have an SSH server installed by default.

    Installing a virtual environment

    Unfortunately, we can't use the built-in venv module to create a virtual environment. Instead, we'll have to work like this. Download the archive with the required python version:
    cd bddt3.site wget https://bootstrap.pypa.io/virtualenv/X.X/virtualenv.pyz
    At the time of writing this article, virtual hosting from timeweb supports only two versions of python:
    1. Python 3.10 - on Ubuntu 22.04
    2. Python 3.6 and Python 2.7 - on Ubuntu 18.04
    Finally, let's create a virtual environment, like this:
    python3 virtualenv.pyz venv
    Now you can activate it and install the necessary packages for our site to work.

    Transferring website files

    The site itself is required for the site to work. It must be somehow transferred to the hosting. Therefore, to transfer site files, you can use the built-in file manager or the terminal command - scp.
    scp (secure copy) — is a command line utility that allows you to securely copy files and directories between two locations (machines/servers).
    And if your project uses a source code version control system, i.e. git. Like me, then you can simply clone the required repository:
    cd ~/bddt3.site/public_htmk && git clone https://github.com/DmRafaule/DjangoDeploymentTest source
    1. Where bddt3.site/public_html is the site directory
    2. Where source is the directory into which the Django site will be cloned
    After successfully transferring the site files, we finally activate the virtual environment and install the necessary packages:
    cd ~/bddt3.site/public_html && source ../venv/bin/activate && pip install -r source/requirements.txt

    Configuration of static and media files

    What do I mean by configuring static and media files? The thing is that when collecting static files or uploading files to the server. They, the files, will be placed in the static and media directories respectively. And these directories, in turn, will be created relative to the root directory of the project. That is, where the manage.py file is located.
    The joke is that the web server does not have access to the root directory of the project, but it does have access to the public_html directory. We need to create static and media directories in public_html, and then create soft links to them from the root directory of the project. This can be done like this:
    cd ~/bddt3.site/public_html/source/Website && mkdir ../../static && mkdir ../../media && ln -s ../../static static && ln -s ../../media media
    A soft link, also known as a symbolic link or symlink, is a special kind of link in a file system that points to another file or directory but does not contain the original file's data.
    The main thing is to be in the directory next to the manage.py file. That's where the soft links should be created.

    Working with hosting configuration files (.htaccess and wsgi.py)

    Setting up .htaccess and wsgi.py files has its own specifics, which are specific only to timeweb hosting. Both .htaccess and wsgi.py files must be in public_html.
    We have the following project structure:
    1. ~/bddt3.site <- You are here
    2. venv
    3. public_html
    4. cgi-bin
    5. media
    6. static
    7. source
    8. Website
    9. Website
    10. settings.py
    11. Frontend
    12. Backend
    13. manage.py
    14. settings.json (This file will be discussed in the next chapter)
    15. media -> ../../media
    16. static -> ../../static
    17. requirements.txt
    18. .htaccess (In this chapter we work with these files)
    19. wsgi.py (In this chapter we work with these files)
    20. index.htm
    The purpose of the .htaccess configuration file is to redirect requests directed to the Apache web server to our Django application. You also need to know one important feature of timeweb hosting. They use a special hosting module for hosting -> mod_wsgi.
    Essentially this means that you will be able to use the WSGI protocol for hosting, but not ASGI.
    WSGI (Web Server Gateway Interface) — a standard for exchanging data between a web server and a web application written in Python, described in the document PEP 333.
    ASGI (Asynchronous Server Gateway Interface) - It is a standard that defines how web servers interact with asynchronous web applications and frameworks in Python.
    Your .htaccess file must contain the following for this to work:
    Options +ExecCGI AddHandler wsgi-script .py RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^(.*)$ /wsgi.py/$1 [QSA,PT]
    You also need to write a simple wsgi (the file should be called wsgi.py) script for work and place it in the same directory next to .htaccess. Here are the contents of the wsgi.py file:
    import os import sys #1 activate_this = os.path.expanduser('~/bddt3.site/venv/bin/activate_this.py') exec(open(activate_this).read(), {'__file__': activate_this}) #2 sys.path.insert(1, os.path.expanduser('~/bddt3.site/public_html/source/Website')) from django.core.wsgi import get_wsgi_application #3 os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'Website.settings') application = get_wsgi_application()
    Everything that is highlighted is what you need to change for your site.
    1. Path to the virtual environment activation script
    2. Path to the root directory of the project (this is where the manage.py file is located)
    3. Path to the settings module (relative to the path specified in the second selection)

    Setting up our Django site

    When you've finished creating and configuring files for the Phusion Passenger gateway and Apache2 web server, you can edit the Django site configuration file, settings.py.
    If you're following my example, you might have noticed that my Django site configuration file is slightly modified. It takes all the configuration data from another file - settings.json.
    from django.utils.translation import gettext_lazy as _ from pathlib import Path import os import json import sys # Build paths inside the project like this: BASE_DIR / 'subdir'. BASE_DIR = Path(__file__).resolve().parent.parent # Read the settings file with open(os.path.join(BASE_DIR,"settings.json"), 'r') as settings_file: settings = json.load(settings_file) # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = settings["SECRET_KEY"] # SECURITY WARNING: don't run with debug turned on in production! DEBUG = settings["DEBUG"] ALLOWED_HOSTS = settings["ALLOWED_HOSTS"] STAGING_SERVER = settings["STAGING_SERVER"] # More code bellow # ...
    An example of what my modified file looks like - settings.py
    The configuration file is located in the root directory of the project, next to manage.py. Its contents will look something like this:
    { "SECRET_KEY": "django-insecure-4#-wrp_(53^0_9$%p8lq+qf43z0fje9iwoeifoweii jjfepiejfh!sa1mfn^l)4-lq@", "DEBUG": false, "ALLOWED_HOSTS": ["bddt3.space"], "DATABASES": { "default": { "ENGINE": "django.db.backends.mysql", "NAME": "cs86772_db", "USERNAME": "cs86772_db", "PASSWORD": "cL1PcShz", "HOST": "localhost" } }, "DEFAULT_FROM_EMAIL": "bddt3@cs86772.tw1.ru", "DEFAULT_TO_EMAIL": "timachuduk@gmail.com", "EMAIL_HOST": "smtp.timeweb.ru", "EMAIL_PORT": 465, "EMAIL_HOST_USER": "bddt3@cs86772.tw1.ru", "EMAIL_HOST_PASSWORD": "D631nL2Fn" }
    This is already a fully configured file using all the data I told you to remember.
    1. To find out what and where to insert for the database, see the chapter on creating a database - Creating a database
    2. To find out what and where to insert for mail, see the chapter on creating and mail - Creating mail
    I changed DEBUG to false because we are deploying a Django project on a production server. You also need to add the name of the domain you purchased to ALLOWED_HOSTS. Plus, don't forget to change SECRET_KEY to a new one.

    Finish up the deployment

    And the final touches to complete the site deployment are the following commands:
    1. Database migration [./manage.py migrate]
    2. Collecting static files [./manage.py collectstatic]
    3. Compilation of translations (if any) [./manage.py compilemessages]
    4. Checking tests (if any) [./manage.py test]
    After successfully completing each of them, you can consider that the site has been successfully deployed.
    I would like to say that you will not be able to compile translations, because the necessary dependencies for this are not installed. Therefore, if you decided that you will make a multilingual site, then you clearly do not need this hosting

    Deploy to VPS

    So, if you read the first part, you couldn't help but notice the significant disadvantages that virtual hosting brings. For example, you won't be able to implement asynchronous communication between the web server and your application (ASGI). Or you won't be able to create a multilingual site.
    On VPS, such difficulties are not expected. And I will show you how to host a site on VPS.

    Create VPS

    VPS and virtual hosting are two different entities and work with them differently. So, to create and manage your virtual machines you will need to go here - https://timeweb.cloud.
    After this page, you will be given the opportunity to configure your server. I will make the most dushmansky server that I can, as always. As a result, the simplest server will cost you 6.37$:
    1. I choose Ubuntu 22.04
    2. Physical location of the server (This is not so important if you use CDN or have a monolingual audience)
    3. What hardware to use (The more complex the project, the cooler you need to take)
    4. Will I have a public IP. That is, will I be able to enter its address in the search and get something
    5. SSH key, for those who are obsessed with security and those who are too lazy to enter a password to log in. (You need to send the public part of the key)

    Editing DNS

    This is done quite quickly. Since we have already purchased a domain, we will only need two records A and AAAA. More specifically, we will need to change the default IP to the IP of our VPS server. On this page, select the VPS that you recently created and copy its IPv4 and IPv6.
    After that we change the DNS records for our domain, in my case it is bddt3.space:
    DNS (Domain Name System) - It is the phone book of the Internet, converting human-readable domain names (like google.com) into the numerical IP addresses that computers use to locate each other. It allows users to access websites and other online resources using easy-to-remember names instead of complex IP addresses.
    Keep in mind that it will take time for the DNS servers to change. How long? It varies, but it took me 15 minutes. Just keep in mind that browsers have their own built-in DNS cache. You can view it by typing this (for Firefox): about:networking#dns.
    Thus, when accessing the specified domain (in my case it is bddt3.space), the DNS server will point to the VPS server we need (that is, the one we created).

    Create a database on VPS

    Any site, one way or another, requires a place to store data. This hosting provider supports many databases (MySQL, PostgreSQL, MongoDB ...). I will demonstrate working with MySQL because I am well acquainted with it.
    So you will create a database and pre-configure it. After its successful deployment (and this takes 5-10 minutes), you will need to edit the settings.json file, but more on that below, but for now I will show you what data we will need to know:
    1. Public IP - 89.169.1.110
    2. User login - gen_user (Default value)
    3. User password - *******
    4. Database name - default_db (Default value)
    5. Connection port - 3306 (Default value)
    This data will be needed in the chapter on connecting to the MySQL database. For now, let's connect to the VPS and transfer the site.

    Connect to the created VPS via SSH

    We have successfully created our first virtual server (and database) on Timeweb, now we need to connect to it. For this we will use SSH. And in order to be able to connect to our server we need to know its IP and password to it. All this comes to the mail that you specified when registering an account on Timeweb.
    SSH (Secure SHell) - is an Internet protocol that enables secure, encrypted communication between a client and a server. There is an SSH client (it is required for the machines from which the connection will be made), and there is an SSH server (it is required if you want to provide remote access to your machine). All servers have an SSH server installed by default.
    Or, alternatively, you can look in the hosting admin panel. Copy the specified command and use it in the terminal:
    The password can be reset if necessary, and the username to which you can always connect is root - always. Let's connect to our server:
    ssh root@92.51.22.80
    Linux machines have SSH client installed by default, but Windows does not. To enable SSH client, you just need to enable this "Feature". Here is a greate article about it.
    And what do you actually connect through? You can use PowerShell, you can use Git Bash if you're used to Linux, you can use specially created programs for connecting to servers via SSH, or you can install a special extension for VSCode and get not only a terminal on a remote server, but also a file manager and development environment - this extension is called Remote - SSH, by the way.
    Since I am still working and sitting on Windows, I will use the simplest and most accessible method, from here on - PowerShell.

    Connect to the server by the key (optional)

    I predict that you will have to log into the remote server very often, if only because the connection can be constantly interrupted, and manually entering the password to connect is quite a task.
    Therefore, I suggest creating a key pair for authorization without a password. To do this, on your work computer, enter the command:
    ssh-keygen -t rsa -f .ssh/bddt3
    1. Where the -t flag is responsible for the type of the generated key
    2. Where the -f flag is responsible for the path to the file (which may not exist) where the key will be saved
    After generation, you will have two files, bddt3 and bddt3.pub. The first (bddt3) is a private key, keep it like the apple of your eye, it is needed for authorization. The second key (bddt3.pub) is distributed to all remote servers that you want to access without entering a password.
    It remains to execute one more command, namely, to transfer the key to the remote server that you want to access using the key.
    ssh-copy-id .ssh/bddt3.pub USERNAME@SERVER
    1. Where .ssh/bddt3.pub is the path to the public part of the key
    2. Where USERNAME is the username through which you want to get to the server, usually root if no other users have been created yet.
    3. Where SERVER is the address of the remote server. This can be either IPv4 or a domain name.
    We are done. After that, to enter the server, use this command:
    ssh USERNAME@SERVER_ADDR -i .ssh/bddt3

    Installing the necessary packages

    Now it's time for Ctrl-C, Ctrl-V. There will be a few commands that will install the necessary packages on your server:
    apt-get update && apt-get upgrade && apt-get install gettext libgettextpo-dev && apt-get install pkg-config default-libmysqlclient-dev build-essential && apt-get install nginx && apt-get install gunicorn &&
    And in order to install the latest versions of Python, you will need to update the Ubuntu package manager repository index.
    add-apt-repository ppa:deadsnakes/ppa && apt-get update
    And then you can install Python and everything you need:
    apt-get install python3.12 python3.12-venv python3.12-dev
    Now let's talk about why I installed all of this, and what each of these commands did:
    1. apt-get update - Always run it first when installing any package. It syncs the application package index and updates all dependencies if necessary.
    2. apt-get upgrade - Installs the latest versions of installed packages on the system.
    3. apt-get install gettext libgettextpo-dev - it installs the dependencies needed to generate translations for your sites (which use the gettext utility)
    4. apt-get install pkg-config default-libmysqlclient-dev build-essential - necessary dependencies for working with MySQL databases.
    5. apt-get install nginx - to start the web server
    6. apt-get install gunicorn - to redirect requests from the nginx server to our django application
    7. apt-get install python3.12 python3-dev python3.12-venv - to be able to create a virtual environment when running python applications
    We are done with installing the necessary packages on the server. Only "unnecessary" ones remain. You can skip to the beginning of the next chapter if you do not have functional tests in the application.
    nginx - It is an easily configurable web server and proxy for requests to be directed to the server.
    gunicorn - This is a server for python applications that connects web servers (such as nginx and apache) and python applications.
    My "unnecessary" package is selenium. I need it for my functional tests to work. And for it to work, it will need the Firefox browser, which we will install as a .deb package. Oh boy, this is quite an adventure \(°〇°)ノ. I invite everyone interested to visit the official Mozilla website and run one command after another.
    In addition to firefox, you will also need to install geckodriver. The latest releases can be found here: https://github.com/mozilla/geckodriver/releases . And now, the command to install this geckodriver:
    wget https://github.com/mozilla/geckodriver/releases/download/v0.36.0/geckodriver-v0.36.0-linux64.tar.gz tar -xzvf geckodriver-v0.36.0-linux64.tar.gz sudo mv geckodriver /usr/local/bin/
    After downloading (wget) and unzipping geckodriver (tar -xzvf), we then placed it in the /usr/local/bin/ directory so that all applications had access to the driver.

    Create a new user

    This step is mandatory and do not think about making a site with root rights. Now you will need to create a user with root privileges and a home directory.
    useradd -m -s /bin/bash site passwd site usermod -aG sudo site
    The first command will create a user named "site", create a home directory for it (flag -m) and set the default shell, i.e. bash. The second command will set a password for the new user. The third will add the user "site" to the sudo group, which is able to execute all commands, only using the sudo command.
    sudo - is a command (program) executed in the terminal on Unix-like operating systems (Linux, MacOS), which allows you to run other programs with permissions to execute administrative and potentially dangerous commands.

    Transferring the project to the server

    The base for our server is ready, now let's work on the site files themselves. I'm going to create a simple file structure where I'll get my project files using git and copy them to the source directory. I'll also create a virtual environment:
    All further commands I executed on behalf of the newly created user "site". If anything changes, I'll let you know.
    mkdir ~/bddt3.space cd ~/bddt3.space git clone https://github.com/DmRafaule/DjangoDeploymentTest source python3.12 -m venv venv
    After running all these commands, you should have the following project structure:
    1. bddt3.space <- You are here
    2. venv
    3. source
    Now, activate the virtual environment and install the necessary packages from source/requirements.txt:
    source ./venv/bin/activate pip install -r source/requirements.txt
    There shouldn't be any problems here, but if they do, read the error logs carefully. Often, these are simply uninstalled dependencies on the server, which can be easily fixed using the apt package manager.
    Let's try to run the installed Django application (from the directory with the manage.py file):
    cd ./source/Website python manage.py runserver

    Setting up mysql database

    You will get an error that the settings.json file was not found. This is a configuration file that I use as a proxy instead of writing directly to settings.py. I did this so that I could safely add the settings.py file to the git repository and to simplify deployment.
    Here is an example of such a file (settings.json), create it in the source/Website directory:
    { "SECRET_KEY": "django-insecure-4#-wrp_(53^0_9$%p8lq+qf43z0dx0ji6bh!sa1mfn^l)4-lq@", "DEBUG": true, "ALLOWED_HOSTS": ["bddt3.space"], "DATABASES": { "default": { "ENGINE": "django.db.backends.mysql", "NAME": "default_db", "USER": "gen_user", "PASSWORD": "aD9bN5oV3pjD7qJ9", "HOST": "89.169.1.110", "PORT": 3306 } }, "EMAIL": { "DEFAULT_FROM_EMAIL": "bddt@bddt.space", "DEFAULT_TO_EMAIL": "chedrden@gmail.com", "EMAIL_HOST": "", "EMAIL_PORT": "" , "EMAIL_HOST_USER": "", "EMAIL_HOST_PASSWORD": "" } , "STAGING_SERVER": "http://staging.bddt3.space" }
    Как ты видишь, я уже использую MySQL в качестве базы данных. Что нужно знать для подключения к базе данных из VPS:
    1. First, you need to know which backend to connect to - django.db.backends.mysql
    2. Second, the database name- default_db
    3. Third, the username - gen_user
    4. Forth, the database password - aD9bN5oV3pjD7qJ9
    5. Fifth, the database host name (address) - 89.169.1.110
    6. Sixth, the connection port - 3306
    All this data can be obtained when creating your database, the process of which I described in the corresponding chapter at the beginning.
    How do I transfer data from settings.json to Website/settings.py? In the settings.py file, I open the settings.json file and read the data from there, like this:
    from django.utils.translation import gettext_lazy as _ from pathlib import Path import os import json import sys # Build paths inside the project like this: BASE_DIR / 'subdir'. BASE_DIR = Path(__file__).resolve().parent.parent # Read the settings file with open(os.path.join(BASE_DIR,"settings.json"), 'r') as settings_file: settings = json.load(settings_file) # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = settings["SECRET_KEY"] # SECURITY WARNING: don't run with debug turned on in production! DEBUG = settings["DEBUG"] ALLOWED_HOSTS = settings["ALLOWED_HOSTS"] STAGING_SERVER = settings["STAGING_SERVER"] # More code bellow # ...
    I use the JSON format because it is simply very convenient to work with it via Python.

    Finishing up the project transfer

    By the way, we can already run tests and see what works and what doesn't. Everything should work. So, we have successfully uploaded our site to the server and even passed all the tests. This means that it is time to configure nginx, after which we will connect our site to the nginx web server via gunicorn.
    Why, and most importantly, why exactly Nginx and Gunicorn? Look, nginx makes our VPS server, as it were, accessible to other machines. It configures port 80 and domain (if necessary) so that other machines know where it is and where to send their requests. But nginx alone is not enough, we need to somehow pass requests from other machines to our Django application. This is what Gunicorn is used for, it also listens on the corresponding port 80 (although it is possible and necessary to do this via UNIX sockets, I will show how), and after receiving a request, it sends it to the Django application, where all the rest of the site logic occurs.

    Super fast Nginx configuration (very optional)

    Next I'm going to go into detail about what each file is used for, how to start and restart nginx, plus how to add sites to nginx. If you're interested, you're welcome, but if not, you can use the server-setup.sh script I left in the repository.
    To use it, enter:
    ./server-setup.sh YOUR_DESIRED_DOMAIN on_https
    1. Where YOUR_DESIRED_DOMAIN is the desired domain
    2. Where on_https is a flag that tells to configure redirect to HTTPS protocol
    This script will create the corresponding configuration files and will be reloaded.

    Configuring Nginx

    Along with the project files, you will also receive default configuration files for configuring nginx - nginx-server-http_only.conf, nginx-server-https_301.conf, nginx-server-https.conf. For now, open the file nginx-server-http_only.conf, you will see the following configuration for our site:
    server { listen 80; server_name HOST_PLACE_SETUP; location /static { root /home/USER_PLACE_SETUP/HOST_PLACE_SETUP; } location /media { root /home/USER_PLACE_SETUP/HOST_PLACE_SETUP; } location / { proxy_set_header Host HOST_PLACE_SETUP; proxy_pass http://unix:/tmp/HOST_PLACE_SETUP.socket; } }
    1. In this configuration, we set up the port on which we will listen for incoming requests.
    2. The name for our server (domain name). In my case, it should be bddt3.space.
    3. The folders that this server will serve. At a minimum, you need to set up the root directory "/". But this is not all, my site uses various statics in the form of pictures and icons. Plus media files that are uploaded directly by the user.
    What are these incomprehensible variables USER_PLACE_SETUP and HOST_PLACE_SETUP? It's all about how my custom server setup script works. In short, it uses the sed command to replace the two above-mentioned variables and replaces them with the values required by the administrator. All this is done through a special server-setup.sh script, which I'll talk about in the next chapter.
    So the final version of this configuration will look like this:
    server { listen 80; server_name bddt3.space; location /static { root /home/site/bddt3.space; } location /media { root /home/site/bddt3.space; } location / { proxy_set_header Host bddt3.space; proxy_pass http://unix:/tmp/bddt3.space.socket; } }
    To make sure we don't forget, let's immediately create the media and static directories in the ~/bddt3.space directory and soft links to them. Soft links to them are created to give the server access to them.
    cd ~/bddt3.space mkdir static mkdir media cd source/Website
    A soft link, also known as a symbolic link or symlink, is a special kind of link in a file system that points to another file or directory but does not contain the original file's data.
    All the necessary directories have been created and now we are ready to create soft links to these directories:
    ln -s ../../static static ln -s ../../media media
    When working with media files, the server can give a 413 response - 413 Request Entity Too large. This is due to the fact that the maximum body size in a request by default can be no more than 1 megabyte. To change this, in the file /etc/nginx/nginx.conf, in the http section, add: ```client_max_body_size 50M;```
    Now, any file that is created in the ~/bddt3.space/source/Website/static or ~/bddt3.space/source/Website/media directory will be available in the ~/bddt3.space/static and ~/bddt3.space/media directories.
    To check this, you can run the collectstatic command and make sure that all files, although copied to ~/bddt3.space/source/Website/static, are also available in ~/bddt3.space/static.

    403 Forbiden error - how to solve (optional, I hope)

    Another very common problem is that the server can return a 403 response to a request for some static file. This is often due to the fact that the user www-data does not have permission to read certain files. The nginx configuration file specifies the user on whose behalf the web server is launched.
    There are three ways to fix this:
    1. Replace the user in the /etc/nginx/nginx.conf file
    2. Give everyone access to read files
    3. Add the user www-data to the group of the user who launches the application.
    I will describe the 3rd because this is, in my opinion, the simplest and most correct way. And you just need to run one command:
    sudo usermod -aG site www-data
    1. site - the name of the group to which you want to add the user (it will match the user name)
    2. www-data - the name of the user you want to join the group.
    Now, all statics and all media files on the site should be available.

    Finish up a Nginx set up

    Let's finish setting up the web server and copy the created configuration file to /etc/nginx/sites-available:
    sudo cp ~/bddt3.space/source/nginx-server.conf /etc/nginx/sites-available/staging-nginx-server.conf
    Now let's do the same as with the static and media directories, create a soft link to this configuration file. But first, go to the directory where this link should be:
    sudo cd /etc/nginx/sites-enabled sudo ln -s ../sites-available/staging-nginx-server.conf staging-nginx-server.conf
    Let's restart the nginx service using systemctl so that the changes take effect:
    sudo systemctl restart nginx
    I think it's worth trying to visit our website now - bddt3.space.
    And yes, you should see something like this. Why is this happening, what is this "Bad Gateway"? It's all because one line, in the site configuration file /etc/nginx/sites-available/staging-nginx-server.conf.
    ... proxy_pass http://unix:/tmp/bddt3.space.socket; ...
    In fact, the nginx server forwarded my GET request to the specified socket, but nothing is connected to it yet. This is where gunicorn comes into play.

    Seting up a Gunicorn

    The almost ready configuration file is located in the same place as the nginx server configuration file - ~/bddt3.space/source/gunicorn.service. This is a file describing the work of the linux daemon, here are its contents:
    [Unit] Description=Gunicorn server for HOST_PLACE_SETUP [Service] Restart=on-failure User=USER_PLACE_SETUP WorkingDirectory=/home/USER_PLACE_SETUP/HOST_PLACE_SETUP/source/Website ExecStart= /home/USER_PLACE_SETUP/HOST_PLACE_SETUP/venv/bin/gunicorn --bind unix:/tmp/HOST_PLACE_SETUP.socket Website.wsgi:application [Install] WantedBy=multi-user.target
    This script has substitution variables HOST_PLACE_SETUP and USER_PLACE_SETUP. I replace them with the values I need via a special script server-setup.sh. More about it in the next chapter.
    This service (daemon), launched by the user site and with its privileges, will be rebooted every time an error occurs (Restart=on-failure). This daemon will work in the directory specified in WorkingDirectory. And it will do what is specified in ExecStart, that is, launch the gunicorn server.
    When launching gunicorn, we also specified which socket to connect to and where to redirect requests - to our Django application.
    Create the same file in /etc/systemd/system/ and edit it by inserting your user, your domain and your socket. Now let's launch the service and make it start on the server after boot.
    sudo cp ~/bddt3.space/source/gunicorn.service /etc/systemd/system/gunicorn.service sudo vim /etc/systemd/system/gunicorn.service sudo systemctl start gunicorn sudo systemctl enable gunicorn
    Now everything will work. We have created a special service that starts the gunicorn server at startup, and it starts our django application. After refreshing the tab, you should see the following:
    This completes the process of deploying a Djanog site on a VPS from reg.ru. I also recommend reading the next chapter on how to put this site on the new HTTPS protocol.

    Migrate to HTTPS (optional, although not really)

    In order to place our site on the HTTPS protocol, we will need to get a special certificate. We will get it from LetsEncrypt. It is free, but what is even cooler is that everything can be done through the command line, which means automation. Look, in order to configure the nginx web server for https, you will need a certificate and a key to it.
    The LetsEncrypt team made a special utility, which is very cool in terms of supported technology stacks for certification. Here, for example, is a page for generating, signing and issuing certificates for sites on nginx and using pip. It is just dope ;) And you do not need this headache with self-signed certificates that no one trusts, and as a result, no one visits the site.
    Activate the virtual environment and install the program:
    source ~/bddt3.space/venv/bin/activate pip install certbot certbot-nginx
    Now we generate and sign up the certificates:
    sudo ~/bddt3.space/venv/bin/certbot certonly --nginx -d bddt3.space
    This command will generate and sign up certificates, which will be placed in /etc/letsencrypt/live/bddt3.space. You will see an interactive prompt like this:
    1. Asks to enter email
    2. Agree to sell your soul and the soul of your site)
    3. Registration, optional
    4. Selecting domains (subdomains) for which this certificate will be valid. If you simply press ENTER, the certificate will be applied to all.
    5. Path to the certificate (for configuring nginx)
    6. Path to the key (for configuring nginx)
    You can also set a cron task to update the certificate every month:
    echo "0 0,12 * * * root /opt/certbot/bin/python -c 'import random; import time; time.sleep(random.random() * 3600)' && sudo certbot renew -q" | sudo tee -a /etc/crontab > /dev/null
    All that remains is to change the configuration in sites-available, this is done like this:
    server { listen 443 ssl; server_name HOST_PLACE_SETUP; ssl_certificate /etc/letsencrypt/live/bddt3.space/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/bddt3.space/privkey.pem; location /static { root /home/USER_PLACE_SETUP/HOST_PLACE_SETUP; } location /media { root /home/USER_PLACE_SETUP/HOST_PLACE_SETUP; } location / { proxy_set_header Host HOST_PLACE_SETUP; proxy_pass http://unix:/tmp/HOST_PLACE_SETUP.socket; } }
    The difference from the previous configuration is that we changed the port and added ssl_certificate and ssl_certificate_key and the paths for which certbot will tell you. That's all, on how to add https to your site.
    But you may have noticed that when trying to get your site via regular http, it will no longer work. You will need to make a separate configuration for port 80 and make a 301 redirect to the https version. This is considered good practice. To do this, create another configuration file in /etc/nginx/sites-available, for example http_301_redirect-staging.bddt.space, with the following:
    server { l isten 80; server_name HOST_PLACE_SETUP; location / { return 301 https://HOST_PLACE_SETUP$request_uri; } }
    Where HOST_PLACE_SETUP is your site's domain, for example bddt3.space. This configuration makes a 301 redirect from any http pages to https pages.
    301 server code - It is also called a permanent redirect, the server response in which a redirection occurs from one URL to another.
    There is also a 302 server code and this is also a redirect. So what is the difference between them? The difference is in the meaning that the 302 code transmits. If 301, then it kind of says: the URL you got will always be available only at the new address. And 302, in turn, says: the URL you got is now available at this address, but it may not always be so.

    Comparison of launching a website on a Hosting and on a VPS

    Testing capabilitiesNo limitNo limit
    Custom project structureLimitedNo limit
    Automation of deploy, setting up etc.LimitedNo limit
    WSGI serverSupportedNo limit
    ASGI serverNot supportedNo limit
    Web serverApache2No limit
    Migration to HTTPSSeamlessHard
    Database setupEasyEasy
    Domain linkingSeamlessEasy
    PriceCheapLess cheap
    TranslationsNot supportedSupported
    MetricsTimeWeb HostingTimeWeb VPS
    Honestly, I would rather deploy sites on a virtual hosting than do it myself on a VPS. But the limitations in the versions of Python used, the inability to use other databases, and the cherry on the cake, the inability to support ASGI and built-in django functionality for localization, really put me off.

    Conclusion

    And here is another hosting provider conquered and studied. Now you know how to host sites on Timeweb. From my experience, I will say that hosting a site on Timeweb is more difficult than on the same beget. There are too many pitfalls and non-obviousness. I hope I have analyzed them all and shown acceptable ways to solve and bypass them.
    I also hope that this article helped you figure out how and where to deploy your site written in Django and I also hope for your kind comment and that you might want to share this article with a friend. In any case, see you in the next article (⌒‿⌒)


    Do not forget to share, like and leave a comment :)

    Comments

    (0)

    captcha
    Send
    LOADING ...
    It's empty now. Be the first (o゚v゚)ノ

    Other

    Similar articles


    How to deploy(host) telegram bot on vps

    Clock
    19.01.2024
    /
    Clock
    05.10.2025
    An eye
    5269
    Hearts
    1
    Connected dots
    0
    Connected dots
    0
    Connected dots
    0
    It is a guide for deploying a telegram bot on VPS. This bot will be written in Python/aiogram. Also you will know how to install, run, and update it. As …

    How to deploy a Django project on Beget (Either via hosting or VPS)

    Clock
    12.05.2024
    /
    Clock
    02.10.2025
    An eye
    3127
    Hearts
    0
    Connected dots
    0
    Connected dots
    0
    Connected dots
    0
    This is an article on how to deploy django site on beget. I show two methods (deployment either on hosting or VPS). Plus, how to set up and connect a …

    How to deploy a Django project on virtual hosting(or VPS) provider reg.ru. Full instruction.

    Clock
    16.03.2025
    /
    Clock
    02.10.2025
    An eye
    1000
    Hearts
    0
    Connected dots
    0
    Connected dots
    0
    Connected dots
    1
    How to deploy a django site on hosting (or VPS) from reg.ru. As well as how to create and configure a DB (including using a cluster in the reg cloud). …