diff --git a/docs/howto/deployment/index.md b/docs/howto/deployment/index.md deleted file mode 100644 index 7de9bb0..0000000 --- a/docs/howto/deployment/index.md +++ /dev/null @@ -1,12 +0,0 @@ -## How to Deploy Bugsink for Production - -To get Bugsink running, you'll need to host it on your own server. This means there's some setup involved. - -But don't stress! We've made deploying Bugsink straightforward. We've minimized complexity to make it as easy as -possible. - -The recommended setup is to deploy Bugsink on a single server, or a virtual one if you prefer. Then, you'll use nginx to -manage incoming requests, directing them to a gunicorn webserver. - -If you have specific deployment preferences or organizational requirements, Bugsink operates like any other Django -application. You can utilize standard Django deployment methods. diff --git a/docs/howto/deployment/single-server.md b/docs/howto/deployment/single-server.md deleted file mode 100644 index c576278..0000000 --- a/docs/howto/deployment/single-server.md +++ /dev/null @@ -1,497 +0,0 @@ -# How to Deploy Bugsink for production on a single-server - -The recommended way to deploy Bugsink is on a single (possibly virtualized) server. - -This minimizes complexity and increases robustness and performance. -It also scales well: A single cheap (e.g. 2GiB RAM, 1 vCPU, XXX disk) server can easily handle up to TODO events per -month, and if you need more than that scaling up the starting point provides ample room for scaling up (bigger -hardware). - -The components you'll set up are: - -* Python -* Bugsink and its dependencies (including Gunicorn) -* A reverse proxy (Nginx) to handle incoming HTTP requests -* SSL certificates -* Snappea, a background process to handle longer-running tasks - -Note that you will _not_ need to set up some of the "usual suspects" like a database server or a message broker. This is -by design: Bugsink uses SQLite (a serverless database) and Snappea (which is brokerless) for its background tasks. - -This guide assumes Ubuntu 24.04 LTS as the operating system. Feel free to use another (Linux) system, though you may -need to substitute commands here and there. - -This guide assumes the following knowledge and starting position: - -* you know your way around the command line and have (root) `ssh` access to a fresh system with the single purpose of - running Bugsink. -* an A-record for your hostname is set up to point to the IP address of your server. - -## Python, pip and venv - -You can verify that Python and Pip are installed by running the following commands: - -```bash -python3 --version -``` - -and - -```bash -pip3 --version -``` - -If either is not, install with - -```bash -apt update -apt upgrade -apt install python3 python3-pip python3-venv -y -``` - -## Set up a non-root user - -It's a good practice to use a non-root user to run the Bugsink server. You can create a new user by running (as root): - -```bash -adduser bugsink --disabled-password --gecos "" -``` - -You can then switch to the new user by running: - -```bash -su - bugsink -``` - -You should now be in `/home/bugsink`. This is where we'll put Bugsink's codebase, the configuration for Bugsink and the -database. - -## Set up a virtual environment and activate it - -It's a good practice to use a virtual environment to manage your Python -dependencies. This way, you can avoid conflicts between different projects. - -Run the following commands to create a virtual environment and activate it: - -```bash -python3 -m venv venv -source venv/bin/activate -``` - -After running these commands, you should see the name of the virtual environment i.e. `(venv)` in your shell prompt. - -## Install Bugsink and its dependencies - -You can install Bugsink using `pip`: - -```bash -python3 -m pip install Bugsink --upgrade -``` - -You should see output indicating that Bugsink and its dependencies are being installed. After the installation is -complete, you can verify that Bugsink is installed by running: - -```bash -bugsink-show-version -``` - - -## Create configuration template - -Bugsink relies on a configuration file to determine how it should run. - -You can create a configuration file that's suitable for production by running the following command (replace `YOURHOST` -with the hostname of your server): - -```bash -bugsink-create-conf --template=recommended --host=YOURHOST -``` - -This will create a file `bugsink_conf.py` in the current directory (which is, assuming you're following along, the -`bugsink` home directory). Open this file in your favorite editor. - -```bash -nano bugsink_conf.py -``` - -The generated template matches the current guide, so in principle you will not need to change much. However, you'll -probably will need to check or adjust at least: - -* `BASE_URL` to match the URL where you want to access Bugsink -* `SITE_NAME` to match the name of your site if you want to distinguish it from other Bugsink instances -* `DEFAULT_FROM_EMAIL` to match the email address from which Bugsink will send emails -* `EMAIL_HOST` and associated variables to match the SMTP server you want to use to send emails -* `TIME_ZONE` to match your timezone (if you want to see times in your local timezone rather than UTC) - -Also noteworthy are the settings that control the "openness" of your particular installation, i.e. whether users can -sign up themselves or need to be invited and whether anybody can start a new team or whether this is managed. Look for - the various `USER_REGISTRATION`-related settings, `SINGLE_USER` and `SINGLE_TEAM` as well as for `TEAM_CREATION`. - - "SINGLE_USER": False, - - "USER_REGISTRATION": CB_ANYBODY, # who can register new users. default: anybody, i.e. users can register themselves - "USER_REGISTRATION_VERIFY_EMAIL": True, - "USER_REGISTRATION_VERIFY_EMAIL_EXPIRY": 3 * 24 * 60 * 60, # 7 days - - # if True, there is only one team, and all projects are in that team - "SINGLE_TEAM": False, - "TEAM_CREATION": CB_MEMBERS, # who can create new teams. default: members, which means "any member of the site" - -## Initialize the database - -Bugsink uses a database to store the data it collects. When set up with Snappea, it also uses a database as a message -queue. - -You can initialize both these databases by running: - -```bash -bugsink-manage migrate -bugsink-manage migrate snappea --database=snappea -``` - -This will create 2 new SQLite database in the location specified in the configuration file (by default: `/home/bugsink`) -and set up the necessary tables. You may verify the presence of the database by running: - -```bash -ls *.sqlite3 -``` - -## Create a superuser - -You can create a superuser account to access the Bugsink admin interface. - -Run the following command and follow the prompts (to stay consistent with usernames in the rest of the system, you may -want to use your email-address as a username): - -```bash -bugsink-manage createsuperuser -``` - -This will create a new user account with administrative privileges. - -## Collect static files - -Bugsink uses static files for its web interface. - -You can collect the static files by running: - -```bash -bugsink-manage collectstatic --noinput -``` - -You should see something like - -``` -123 static files copied to '/home/bugsink/venv/lib/python3.12/site-packages/collectedstatic/' -``` - - -## Set up Gunicorn (managed by Systemd) - -We will run Bugsink using Gunicorn, a WSGI server. - -Gunicorn was already installed as part of the Bugsink dependencies, so we just need to run it. - -Rather than running Gunicorn directly, [we will use a systemd service to manage the process](https://docs.gunicorn.org/en/latest/deploy.html#systemd). - -Exit the `bugsink` user by running: - -```bash -exit -``` - -This should bring you back to the root user. - -Create a file: - -`/etc/systemd/system/gunicorn.service` with the following contents: - -```ini -[Unit] -Description=gunicorn daemon -After=network.target - -[Service] -Restart=always -Type=notify -User=bugsink -Group=bugsink - -Environment="PYTHONUNBUFFERED=1" -RuntimeDirectory=gunicorn -WorkingDirectory=/home/bugsink -ExecStart=/home/bugsink/venv/bin/gunicorn --bind="127.0.0.1:8000" --workers=5 --access-logfile - --capture-output --error-logfile - --max-requests=1000 --max-requests-jitter=100 bugsink.wsgi -KillMode=mixed -TimeoutStopSec=5 - -[Install] -WantedBy=multi-user.target -``` - -(In the example above we have set the number of workers to 5; a good starting point for this value in general is the -number of CPU cores on your server * 2 + 1, as per the [Gunicorn -documentation](https://docs.gunicorn.org/en/latest/design.html#how-many-workers)) - -Enable and start the service (enabling means it will also start on boot): - -```bash -systemctl enable --now gunicorn.service -``` - -Inspect the status of gunicorn using - -```bash -systemctl status gunicorn.service -``` - -To test whether gunicorn actually listens on the socket, and whether everything can be reached, use: - -```bash -curl http://localhost:8000/accounts/login/ -``` - -This should dump a bunch of html on screen. - - -## Set up Nginx to run on port 80 - -We will first set up Nginx to run on port 80; when this is running correctly, we can use certbot to set up SSL -automatically. - -Install nginx: - -```bash -apt install nginx -``` - -To verify that nginx is running, and that your DNS record is pointing to your server, you may enter the hostname of your -server in your browser. You should see the default nginx welcome page ("Welcome to nginx!"). - -Remove the default configuration file: - -```bash -rm /etc/nginx/sites-enabled/default -``` - -Create a configuration file for your site (`/etc/nginx/sites-available/bugsink`) with the following contents: - - -``` -server { - server_name YOURHOST; - listen 80; - location / { - proxy_pass http://127.0.0.1:8000; - proxy_set_header Host $host; - } -} -``` - -(YOURHOST should be replaced with the full hostname of your server). - -Create a link from `sites-enabled` to `sites-available`: - -```bash -ln -s /etc/nginx/sites-available/bugsink /etc/nginx/sites-enabled -``` - -Check the configuration file for syntax errors: - -```bash -service nginx configtest -``` - -If there are no errors, restart nginx: - -```bash -systemctl restart nginx -``` - -You should now be able to access Bugsink by going to `http://YOURHOST` in your browser. - -Congratulations! Resist the temptation to log in... set up SSL first. - -## Setting up SSL - -To set up SSL, we will use certbot, a tool that automates the process of obtaining and renewing SSL certificates. Certbot -is available as a snap package. - -```bash -snap install --classic certbot -sudo ln -s /snap/bin/certbot /usr/bin/certbot -``` - -Then, run certbot (following the instructions on the prompt). - -We will use the `--nginx` plugin to automatically configure Nginx to use the SSL certificate. `--no-redirect` is used -to avoid redirecting all HTTP traffic to HTTPS; we will set this up manually in the Nginx in the next step. - -```bash -certbot --nginx --rsa-key-size 4096 --no-redirect -``` - -(If you wish, you can take a look at the configuration file in `/etc/nginx/sites-available/bugsink` to see how certbot -has modified it). - -After this step you should be able to access Bugsink using HTTPS; open your browser and enter the hostname of your -server, but with `https` instead of `http`. You should see the Bugsink interface, and the browser should indicate that -the connection is secure. - -## Final Nginx configuration - -To avoid accidentally using the unencrypted version of the site, it's a good idea to - -* set up automatic redirects from HTTP -* avoid host spoofing by setting up a catch-all `server_name` directive -* Use HSTS to ensure that browsers only connect to your site over HTTPS - -A complete nginx configuration file could look like this: - - -``` -# Disable nginx version number in headers (unnecessary information for potential attackers) -server_tokens off; - -# Catch-all server block to avoid host spoofing, i.e. to ensure that the server only responds to requests for the -# correct hostname -server { - listen 80 default_server; - return 444; -} - -# Redirect HTTP to HTTPS -server { - server_name YOURHOST; - listen 80; - return 307 https://$host$request_uri; -} - -server { - server_name YOURHOST; - - # this matches the default configuration for MAX_ENVELOPE_COMPRESSED_SIZE. Note that Nginx's "M" means MiB. - client_max_body_size 20M; - - access_log /var/log/nginx/bugsink.access.log; - error_log /var/log/nginx/bugsink.error.log; - - - location / { - # Pass the request to Gunicorn via proxy_pass. - proxy_pass http://127.0.0.1:8000; - - # Set the Host header to the original host. - proxy_set_header Host $host; - - # Set the X-Forwarded-Proto header to the original scheme; because Django/Bugsink is behind a proxy, it needs - # to know the original scheme to know whether the current request is secure or not. This directive corresponds - # to the setting "SECURE_PROXY_SSL_HEADER" in your bugsink_conf.py file. - proxy_set_header X-Forwarded-Proto $scheme; - - # Because the server is behind a proxy, it needs to know the original IP address of the client. This information - # is passed on in the X-Forwarded-For header, and picked up by Bugsink because of the setting "USE_X_FORWARDED_FOR" - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - - # Set up HSTS with a long max-age (1 year) and the "preload" directive, which tells browsers to include your - # site in their HSTS preload list. This means that browsers will only connect to your site over HTTPS, even if - # the user types in the URL without the "https://" prefix. - add_header Strict-Transport-Security "max-age=31536000; preload" always; - } - - # This whole block is auto-generated by Certbot; Alternatively, use the block below from the previous version of - # the configuration file, i.e. the version of the file right after you ran certbot: - listen 443 ssl; # managed by Certbot - ssl_certificate /etc/letsencrypt/live/YOURHOST/fullchain.pem; # managed by Certbot - ssl_certificate_key /etc/letsencrypt/live/YOURHOST/privkey.pem; # managed by Certbot - include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot - ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot -} -``` - -Again, replace `YOURHOST` with the hostname of your server. (Note that you cannot skip to this step without first -setting up a port-80 configuration file as described above, because certbot will not be able to verify your domain -otherwise.) - -Make sure to check the configuration file for syntax errors, and restart nginx after making changes: - -``` -service nginx configtest -systemctl restart nginx -``` - - -## Set up Snappea - -Snappea is a brokerless service for background tasks. - -We will set up Snappea to run as a systemd service. - -Add a file `/etc/systemd/system/snappea.service` with the following contents: - -```ini -[Unit] -Description=snappea daemon - -[Service] -Restart=always -User=bugsink -Group=bugsink - -Environment="PYTHONUNBUFFERED=1" -RuntimeDirectory=gunicorn -WorkingDirectory=/home/bugsink -ExecStart=/home/bugsink/venv/bin/bugsink-runsnappea -KillMode=mixed -TimeoutStopSec=5 -RuntimeMaxSec=1d - -[Install] -WantedBy=multi-user.target -``` - -Enable and start the service by running: - -```bash -systemctl enable --now snappea.service -``` - -You may check whether this was successful by running: - -```bash -systemctl status snappea.service -``` - -To ensure that Snappea is actually picking up tasks, you may additionally do the following: - -``` -# log in as bugsink user -su - bugsink - -# activate the virtual environment -source venv/bin/activate - -# run the following command to add a task to the queue -bugsink-manage checksnappea - -# exit back to root -exit -``` - -The snappea journal should then show that the task was picked up and executed. Check by running: - -```bash -journalctl -u snappea.service -``` - -This should show a log entry indicating that the task was picked up and executed: - -``` -Starting 000-001 for "snappea.example_tasks.fast_task" with (), {} -Worker done in 0.000s -``` - -## Start using Bugsink - -With snappea set up you're ready to actually start using Bugsink. - -Log in with the superuser credentials you set up earlier and configure your first project. diff --git a/docs/tutorials/local-install.md b/docs/tutorials/local-install.md deleted file mode 100644 index c68db27..0000000 --- a/docs/tutorials/local-install.md +++ /dev/null @@ -1,145 +0,0 @@ -# Quick install guide - -Before you can use Bugsink, you'll need to install it. We have a [comprehensive -guide](/how-to/install) that covers all the details, but if you just want to get -started quickly on your local development environment, here's a quick guide. - -Running locally is a great way to determine if Bugsink is right for you and is -even easier to set up than a production environment. Bugsink's License allows -you to run it for a single user on your local machine for free. - -## Install Python - -Bugsink is written in Python, so you need to have Python installed on your -system. You can download Python from the [official -website](https://www.python.org/downloads/) or using a package manager like -`apt` or `brew`. - -You can verify that Python is installed by running the following command: - -```bash -python --version -``` - -## Set up a working dir - -Both the Bugsink code and the data it collects will be stored somewhere. - -Create a new directory and navigate to it: - -```bash -mkdir bugsink -cd bugsink -``` - -## Set up a virtual environment and activate it - -It's a good practice to use a virtual environment to manage your Python -dependencies. This way, you can avoid conflicts between different projects. - -Run the following commands to create a virtual environment and activate it: - -```bash -python -m venv . -source bin/activate -``` - -After running these commands, you should see the name of the virtual environment -in your shell prompt. - -## Install Bugsink and its dependencies - -You can install Bugsink using `pip`: - -```bash -python -m pip install bugsink --upgrade -``` - -You should see output indicating that Bugsink and its dependencies are being -installed. After the installation is complete, you can verify that Bugsink is -installed by running: - -```bash -bugsink-show-version -``` - -## Create configuration template - -Bugsink relies on a configuration file to determine how it should run. - -You can create a configuration file that's suitable for local development by -running: - -```bash -bugsink-create-conf --template=local --port=9000 -``` - -This will create a file `bugsink_conf.py` in the current directory. You may -later edit this file to customize the configuration, but for this tutorial, the -default configuration should be sufficient. - -## Initialize the database - -Bugsink uses a database to store the data it collects. - -You can initialize the database by running: - -```bash -bugsink-manage migrate -``` - -This will create a new SQLite database in the current directory and set up the -necessary tables. You may verify the presence of the database by running - -```bash -ls db.sqlite3 -``` - -## Create a superuser - -You can create a superuser account to access the Bugsink admin interface. - -Run the following command and follow the prompts: - -```bash -bugsink-manage createsuperuser -``` - -This will create a new user account with administrative privileges. - -## Collect static files - -Bugsink uses static files for its web interface. - -You can collect the static files by running: - -```bash -bugsink-manage collectstatic --noinput -``` - -You should see something like - -``` -123 static files copied to '/path/to/your/working/dir/collectedstatic'. -``` - - -## Run the Bugsink server - -The recommended way to run Bugsink is using Gunicorn, a WSGI server. - -You can start the Bugsink server by running: - -```bash -PYTHONUNBUFFERED=1 gunicorn --bind="127.0.0.1:9000" --workers=2 --access-logfile - --capture-output --error-logfile - bugsink.wsgi -``` - -You should see output indicating that the server is running. You can now access Bugsink by visiting -http://127.0.0.1:9000/ in your web browser. - - - -## Next steps - -You've successfully installed Bugsink on your local machine! You can now start -using it to collect crash reports for your (local) applications.