From 627b5c1ff7b6856f1b83da5b6d1acd5cf597b266 Mon Sep 17 00:00:00 2001 From: David Luevano Alvarado Date: Sun, 23 Jul 2023 22:31:37 -0600 Subject: add new built files --- live/blog/rss.xml | 900 +++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 854 insertions(+), 46 deletions(-) (limited to 'live/blog/rss.xml') diff --git a/live/blog/rss.xml b/live/blog/rss.xml index 12a2e7c..8494c6f 100644 --- a/live/blog/rss.xml +++ b/live/blog/rss.xml @@ -22,6 +22,813 @@ Luévano's Blog https://blog.luevano.xyz + + Set up a media server with Jellyfin with Sonarr and Radarr + https://blog.luevano.xyz/a/jellyfin_server_with_sonarr_radarr.html + https://blog.luevano.xyz/a/jellyfin_server_with_sonarr_radarr.html + Mon, 24 Jul 2023 04:30:14 GMT + Code + English + Server + Tools + Tutorial + How to set up a media server with Jellyfin with Sonarr and Radarr, on Arch. With Bazarr, too. + Second part of my self hosted media server. This is a direct continuation of Set up qBitTorrent with Jackett for use with Starr apps, which will be mentioned as “first part” going forward. Sonarr, Radarr, Bazarr (Starr apps) and Jellyfin setups will be described in this part. Same introduction applies to this entry, regarding the use of documentation and configuration.

+

Everything here is performed in arch btw and all commands should be run as root unless stated otherwise.

+

Kindly note that I do not condone the use of BitTorrent for illegal activities. I take no responsibility for what you do when setting up anything shown here. It is for you to check your local laws before using automated downloaders such as Sonarr and Radarr.

+

Table of contents

+ +

Prerequisites

+

Same prerequisites as with the First part: Prerequisites plus:

+
    +
  • An A (and/or AAAA) or a CNAME for jellyfin. Only if you want to expose Jellyfin to a subdomain.
  • +
+

The First part: Directory structure is the same here. The servarr user and group should be available, too.

+

It is assumed that the first part was followed.

+

Radarr

+

Radarr is a movie collection manager that can be used to download movies via torrents. This is actually a fork of Sonarr, so they’re pretty similar, I just wanted to set up movies first.

+

Install from the AUR with yay:

+
yay -S radarr
+
+

Add the radarr user to the servarr group:

+
gpasswd -a radarr servarr
+
+

The default port that Radarr uses is 7878 for http (the one you need for the reverse proxy).

+

Reverse proxy

+

Add the following location blocks into the isos.conf with whatever subdirectory name you want, I’ll leave it as radarr:

+
location /radarr/ {
+    proxy_pass http://127.0.0.1:7878/radarr/; # change port if needed
+    proxy_http_version 1.1;
+
+    proxy_set_header Host $host;
+    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+    proxy_set_header X-Forwarded-Host $host;
+    proxy_set_header X-Forwarded-Proto $scheme;
+    proxy_set_header Upgrade $http_upgrade;
+    proxy_set_header Connection $http_connection;
+
+    proxy_redirect off;
+}
+# Allow the API External Access via NGINX
+location /radarr/api {
+    auth_basic off;
+    proxy_pass http://127.0.0.1:7878/radarr/api; # change port if needed
+}
+
+

This is taken from Radarr Nginx reverse proxy configuration. Restart the nginx service for the changes to take effect:

+
systemctl restart nginx.service
+
+

Start using Radarr

+

You can now start/enable the radarr.service:

+
systemctl enable radarr.service
+systemctl start radarr.service
+
+

This will start the service and create the default configs under /var/lib/radarr. You need to change the URLBase as the reverse proxy is under a subdirectory (/radarr). Edit /var/lib/radarr/config.xml:

+
...
+<UrlBase>/radarr</UrlBase>
+...
+
+

Then restart the radarr service:

+
systemctl restart radarr.service
+
+

Now https://isos.yourdomain.com/radarr is accessible. Secure the instance right away by adding authentication under Settings -> General -> Security. I added the “Forms” option, just fill in the username and password then click on save changes on the top left of the page. You can restart the service again and check that it asks for login credentials.

+

Note that if you want to have an anime movies library, it is recommended to run a second instance of Radarr for this as shown in Radarr: Linux multiple instances and follow TRaSH: How to setup quality profiles anime if an anime instance is what you want.

+

Configuration

+

Will be following the official Radarr: Quick start guide as well as the recommendations by TRaSH: Radarr.

+

Anything that is not mentioned in either guide or that is specific to how I’m setting up stuff will be stated below.

+
Media Management
+ +
Quality
+

This is personal preference and it dictates your preferred file sizes. You can follow TRaSH: Quality settings to maximize the quality of the downloaded content and restrict low quality stuff.

+

Personally, I think TRaSH’s quality settings are a bit elitist and first world-y. I’m fine with whatever and the tracker I’m using has the quality I want anyways. I did, however, set it to a minimum of 0 and maximum of 400 for the qualities shown in TRaSH’s guide. Configuring anything below 720p shouldn’t be necessary anyways.

+
Custom Formats
+

Again, this is also completely a personal preference selection and depends on the quality and filters you want. My custom format selections are mostly based on TRaSH: HD Bluray + WEB quality profile.

+

The only Unwanted format that I’m not going to use is the Low Quality (LQ) as it blocks one of the sources I’m using to download a bunch of movies. The reasoning behind the LQ custom format is that these release groups don’t care much about quality (they keep low file sizes) and name tagging, which I understand but I’m fine with this as I can upgrade movies individually whenever I want (I want a big catalog of content that I can quickly watch).

+
Profiles
+

As mentioned in Custom Formats and Quality this is completly a personal preference. I’m going to go for “Low Quality” downloads by still following some of the conventions from TRaSH. I’m using the TRaSH: HD Bluray + WEB quality profile with the exclusion of the LQ profile.

+

I set the name to “HD Bluray + WEB”. I’m also not upgrading the torrents for now. Language set to “Original”.

+
Download clients
+

Pretty straight forward, just click on the giant “+” button and click on the qBitTorrent option. Then configure:

+
    +
  • Name: can be anything, just an identifier.
  • +
  • Enable: enable it.
  • +
  • Host: use 127.0.0.1. For some reason I can’t make it work with the reverse proxied qBitTorrent.
  • +
  • Port: the port number you chose, 30000 in my case.
  • +
  • Url Base: leave blank as even though you have it exposed under /qbt, the service itself is not.
  • +
  • Username: the Web UI username, admin by default.
  • +
  • Password: the Web UI username, adminadmin by default (you should’ve changed it if you have the service exposed).
  • +
  • Category: movies.
  • +
+

Everything else can be left as default, but maybe change Completed Download Handling if you’d like. Same goes for the general Failed Download Handling download clients’ option.

+
Indexers
+

Also easy to set up, also just click on the giant “+” button and click on the custom Torznab option (you can also use the preset -> Jackett Torznab option). Then configure:

+
    +
  • Name: can be anything, just an identifier. I like to do “Jackett - INDEXER”, where “INDEXER” is just an identifier.
  • +
  • URL: http://127.0.0.1:9117/jack/api/v2.0/indexers/YOURINDEXER/results/torznab/, where YOURINDEXER is specific to each indexer (yts, nyaasi, etc.). Can be directly copied from the indexer’s “Copy Torznab Feed” button on the Jackett Web UI.
  • +
  • API Path: /api, leave as is.
  • +
  • API Key: this can be found at the top right corner in Jackett’s Web UI.
  • +
  • Categories: which categories to use when searching, these are generic categories until you test/add the indexer. After you add the indexer you can come back and select your prefered categories (like just toggling the movies categories).
  • +
  • Tags: I like to add a tag for the indexer name like yts or nyaa. This is useful to control which indexers to use when adding new movies.
  • +
+

Everything else on default. Download Client can also be set, which can be useful to keep different categories per indexer or something similar. Seed Ratio and Seed Time can also be set and are used to manage when to stop the torrent, this can also be set globally on the qBitTorrent Web UI, this is a personal setting.

+

Download content

+

You can now start to download content by going to Movies -> Add New. Basically just follow the Radarr: How to add a movie guide. The screenshots from the guide are a bit outdated but it contains everything you need to know.

+

I personally use:

+
    +
  • Monitor: Movie Only.
  • +
  • Minimum Availability: Released.
  • +
  • Quiality Profile: “HD Bluray + WEB”, the one configured in this entry.
  • +
  • Tags: the indexer name I want to use to download the movie, usually just yts for me (remember this is a “LQ” release group, so if you have that custom format disable it) as mentioned in Indexers. If you don’t specify a tag it will only use indexers that don’t have a tag set.
  • +
  • Start search for missing movie: toggled on. Immediatly start searching for the movie and start the download.
  • +
+

Once you click on “Add Movie” it will add it to the Movies section and start searching and selecting the best torrent it finds, according to the “filters” (quality settings, profile and indexer(s)).

+

When it selects a torrent it sends it to qBitTorrent and you can even go ahead and monitor it over there. Else you can also monitor at Activity -> Queue.

+

After the movie is downloaded and processed by Radarr, it will create the appropriate hardlinks to the media/movies directory, as set in First part: Directory structure.

+

Optionally, you can add subtitles using Bazarr.

+

Sonarr

+

Sonarr is a TV series collection manager that can be used to download series via torrents. Most of the install process, configuration and whatnot is going to be basically the same as with Radarr.

+

Install from the AUR with yay:

+
yay -S sonarr
+
+

Add the sonarr user to the servarr group:

+
gpasswd -a sonarr servarr
+
+

The default port that Radarr uses is 8989 for http (the one you need for the reverse proxy).

+

Reverse proxy

+

Basically the same as with Radarr: Reverse proxy, except that the proxy_set_header changes from $proxy_host to $host.

+

Add the following location blocks into the isos.conf, I’ll leave it as sonarr:

+
location /sonarr/ {
+    proxy_pass http://127.0.0.1:8989/sonarr/; # change port if needed
+    proxy_http_version 1.1;
+
+    proxy_set_header Host $proxy_host; # this differs from the radarr reverse proxy
+    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+    proxy_set_header X-Forwarded-Host $host;
+    proxy_set_header X-Forwarded-Proto $scheme;
+    proxy_set_header Upgrade $http_upgrade;
+    proxy_set_header Connection $http_connection;
+
+    proxy_redirect off;
+}
+# Allow the API External Access via NGINX
+location /sonarr/api {
+    auth_basic off;
+    proxy_pass http://127.0.0.1:8989/sonarr/api; # change port if needed
+}
+
+

This is taken from Sonarr: Nginx reverse proxy configuration. Restart the nginx service for the changes to take effect:

+
systemctl restart nginx.service
+
+

Start using Sonarr

+

You can now start/enable the sonarr.service:

+
systemctl enable sonarr.service
+systemctl start sonarr.service
+
+

This will start the service and create the default configs under /var/lib/sonarr. You need to change the URLBase as the reverse proxy is under a subdirectory (/sonarr). Edit /var/lib/sonarr/config.xml:

+
...
+<UrlBase>/sonarr</UrlBase>
+...
+
+

Then restart the sonarr service:

+
systemctl restart sonarr.service
+
+

Now https://isos.yourdomain.com/sonarr is accessible. Secure the instance right away by adding authentication under Settings -> General -> Security. I added the “Forms” option, just fill in the username and password then click on save changes on the top left of the page. You can restart the service again and check that it asks for login credentials.

+

Similar to Radarr if you want to have an anime library, it is recommended to run a second instance of Sonarr for this as shown in Sonarr: Linux multiple instances and follow TRaSH: Release profile regex (anime) and the TRaSH: Anime recommended naming scheme if an anime instance is what you want.

+

Configuration

+

Will be following the official Sonarr: Quick start guide as well as the recommendations by TRaSH: Sonarr.

+

Anything that is not mentioned in either guide or that is specific to how I’m setting up stuff will be stated below.

+
Media Management
+ +
Quality
+

Similar to Radarr: Quality this is personal preference and it dictates your preferred file sizes. You can follow TRaSH: Quality settings to maximize the quality of the downloaded content and restrict low quality stuff.

+

Will basically do the same as in Radarr: Quality: set minimum of 0 and maximum of 400 for everything 720p and above.

+
Profiles
+

This is a bit different than with Radarr, the way it is configured is by setting “Release profiles”. I took the profiles from TRaSH: WEB-DL Release profile regex. The only possible change I’ll do is disable the Low Quality Groups and/or the “Golden rule” filter (for x265 encoded video).

+

For me it ended up looking like this:

+
+Sonarr: Release profiles +
Sonarr: Release profiles
+
+

But yours can differ as its mostly personal preference. For the “Quality profile” I’ll be using the default “HD-1080p” most of the time, but I also created a “HD + WEB (720/1080)” which works best for some.

+
Download clients
+

Exactly the same as with Radarr: Download clients only change is the category from movies to tv (or whatever you want), click on the giant “+” button and click on the qBitTorrent option. Then configure:

+
    +
  • Name: can be anything, just an identifier.
  • +
  • Enable: enable it.
  • +
  • Host: use 127.0.0.1.
  • +
  • Port: the port number you chose, 30000 in my case.
  • +
  • Url Base: leave blank as even though you have it exposed under /qbt, the service itself is not.
  • +
  • Username: the Web UI username, admin by default.
  • +
  • Password: the Web UI username, adminadmin by default (you should’ve changed it if you have the service exposed).
  • +
  • Category: tv.
  • +
+

Everything else can be left as default, but maybe change Completed Download Handling if you’d like. Same goes for the general Failed Download Handling download clients’ option.

+
Indexers
+

Also exactly the same as with Radarr: Indexers, click on the giant “+” button and click on the custom Torznab option (this doesn’t have the Jackett preset). Then configure:

+
    +
  • Name: can be anything, just an identifier. I like to do “Jackett - INDEXER”, where “INDEXER” is just an identifier.
  • +
  • URL: http://127.0.0.1:9117/jack/api/v2.0/indexers/YOURINDEXER/results/torznab/, where YOURINDEXER is specific to each indexer (eztv, nyaasi, etc.). Can be directly copied from the indexer’s “Copy Torznab Feed” button on the Jackett Web UI.
  • +
  • API Path: /api, leave as is.
  • +
  • API Key: this can be found at the top right corner in Jackett’s Web UI.
  • +
  • Categories: which categories to use when searching, these are generic categories until you test/add the indexer. After you add the indexer you can come back and select your prefered categories (like just toggling the TV categories).
  • +
  • Tags: I like to add a tag for the indexer name like eztv or nyaa. This is useful to control which indexers to use when adding new series.
  • +
+

Everything else on default. Download Client can also be set, which can be useful to keep different categories per indexer or something similar. Seed Ratio and Seed Time can also be set and are used to manage when to stop the torrent, this can also be set globally on the qBitTorrent Web UI, this is a personal setting.

+

Download content

+

Almost the same as with Radarr: Download content, but I’ve been personally selecting the torrents I want to download for each season/episode so far, as the indexers I’m using are all over the place and I like consistencies. Will update if I find a (near) 100% automation process, but I’m fine with this anyways as I always monitor that everything is going fine.

+

Add by going to Series -> Add New. Basically just follow the Sonarr: Library add new guide. Adding series needs a bit more options that movies in Radarr, but it’s straight forward.

+

I personally use:

+
    +
  • Monitor: All Episodes.
  • +
  • Quiality Profile: “HD + WEB (720/1080)”. This depends on what I want for that how, lately I’ve been experimenting with this one.
  • +
  • Series Type: Standard. For now I’m just downloading shows, but it has an Anime option.
  • +
  • Tags: the “indexer_name” I want to use to download the movie, I’ve been using all indexers so I just use all tags as I’m experimenting and trying multiple options.
  • +
  • Season Folder: enabled. I like as much organization as possible.
  • +
  • Start search for missing episodes: disabled. Depends on you, due to my indexers, I prefer to check manually the season packs, for example.
  • +
  • Start search for cutoff unmet episodes: disabled. Honestly don’t really know what this is.
  • +
+

Once you click on “Add X” it will add it to the Series section and will start as monitored. So far I haven’t noticed that it immediately starts downloading (because of the “Start search for missing episodes” setting) but I always click on unmonitor the series, so I can manually check (again, due to the low quality of my indexers).

+

When it automatically starts to download an episode/season it will send it to qBitTorrent and you can monitor it over there. Else you can also monitor at Activity -> Queue. Same thing goes if you download manually each episode/season via the interactive search.

+

To interactively search episodes/seasons go to Series and then click on any series, then click either on the interactive search button for the episode or the season, it is an icon of a person as shown below:

+
+Sonarr: Interactive search button +
Sonarr: Interactive search button
+
+

Then it will bring a window with the search results, where it shows the indexer it got the result from, the size of the torrent, peers, language, quality, the score it received from the configured release profiles an alert in case that the torrent is “bad” and the download button to manually download the torrent you want. An example shown below:

+
+Sonarr: Interactive search results +
Sonarr: Interactive search results
+
+

After the movie is downloaded and processed by Sonarr, it will create the appropriate hardlinks to the media/tv directory, as set in Directory structure.

+

Optionally, you can add subtitles using Bazarr.

+

Jellyfin

+

Jellyfin is a media server “manager”, usually used to manage and organize video content (movies, TV series, etc.) which could be compared with Plex or Emby for example (take them as possible alternatives).

+

Install from the AUR with yay:

+
yay -S jellyfin-bin
+
+

I’m installing the pre-built binary instead of building it as I was getting a lot of errors and the server was even crashing. You can try installing jellyfin instead.

+

Add the jellyfin user to the servarr group:

+
gpasswd -a jellyfin servarr
+
+

You can already start/enable the jellyfin.service which will start at http://127.0.0.1:8096/ by default where you need to complete the initial set up. But let’s create the reverse proxy first then start everything and finish the set up.

+

Reverse proxy

+

I’m going to have my jellyfin instance under a subdomain with an nginx reverse proxy as shown in the Arch wiki. For that, create a jellyfin.conf at the usual sites-<available/enabled> path for nginx:

+
server {
+    listen 80;
+    server_name jellyfin.yourdomain.com; # change accordingly to your wanted subdomain and domain name
+    set $jellyfin 127.0.0.1; # jellyfin is running at localhost (127.0.0.1)
+
+    # Security / XSS Mitigation Headers
+    add_header X-Frame-Options "SAMEORIGIN";
+    add_header X-XSS-Protection "1; mode=block";
+    add_header X-Content-Type-Options "nosniff";
+
+    # Content Security Policy
+    # See: https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP
+    # Enforces https content and restricts JS/CSS to origin
+    # External Javascript (such as cast_sender.js for Chromecast) must be whitelisted.
+    add_header Content-Security-Policy "default-src https: data: blob: http://image.tmdb.org; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' https://www.gstatic.com/cv/js/sender/v1/cast_sender.js https://www.youtube.com blob:; worker-src 'self' blob:; connect-src 'self'; object-src 'none'; frame-ancestors 'self'";
+
+        location = / {
+        return 302 https://$host/web/;
+    }
+
+    location / {
+        # Proxy main Jellyfin traffic
+        proxy_pass http://$jellyfin:8096;
+        proxy_set_header Host $host;
+        proxy_set_header X-Real-IP $remote_addr;
+        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+        proxy_set_header X-Forwarded-Proto $scheme;
+        proxy_set_header X-Forwarded-Protocol $scheme;
+        proxy_set_header X-Forwarded-Host $http_host;
+
+        # Disable buffering when the nginx proxy gets very resource heavy upon streaming
+        proxy_buffering off;
+    }
+
+    # location block for /web - This is purely for aesthetics so /web/#!/ works instead of having to go to /web/index.html/#!/
+    location = /web/ {
+        # Proxy main Jellyfin traffic
+        proxy_pass http://$jellyfin:8096/web/index.html;
+        proxy_set_header Host $host;
+        proxy_set_header X-Real-IP $remote_addr;
+        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+        proxy_set_header X-Forwarded-Proto $scheme;
+        proxy_set_header X-Forwarded-Protocol $scheme;
+        proxy_set_header X-Forwarded-Host $http_host;
+    }
+
+    location /socket {
+        # Proxy Jellyfin Websockets traffic
+        proxy_pass http://$jellyfin:8096;
+        proxy_http_version 1.1;
+        proxy_set_header Upgrade $http_upgrade;
+        proxy_set_header Connection "upgrade";
+        proxy_set_header Host $host;
+        proxy_set_header X-Real-IP $remote_addr;
+        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+        proxy_set_header X-Forwarded-Proto $scheme;
+        proxy_set_header X-Forwarded-Protocol $scheme;
+        proxy_set_header X-Forwarded-Host $http_host;
+    }
+}
+
+

SSL certificate

+

Create/extend the certificate by running:

+
certbot --nginx
+
+

Similarly to the isos subdomain, that will autodetect the new subdomain and extend the existing certificate(s). Restart the nginx service for changes to take effect:

+
systemctl restart nginx.service
+
+

Start using Jellyfin

+

You can now start/enable the jellyfin.service if you haven’t already:

+
systemctl enable jellyfin.service
+systemctl start jellyfin.service
+
+

Then navigate to https://jellyfin.yourdomain.com and either continue with the set up wizard if you didn’t already or continue with the next steps to configure your libraries.

+

The initial setup wizard makes you create an user (will be the admin for now) and at least one library, though these can be done later. For more check Jellyfin: Quick start.

+

Remember to use the configured directory as mentioned in Directory structure. Any other configuration (like adding users or libraries) can be done at the dashboard: click on the 3 horizontal lines on the top left of the Web UI then navigate to Administration -> Dashboard. I didn’t configure much other than adding a couple of users for me and friends, I wouldn’t recommend using the admin account to watch (personal preference).

+

Once there is at least one library it will show at Home along with the latest movies (if any) similar to the following (don’t judge, these are just the latest I added due to friend’s requests):

+
+Jellyfin: Home libraries +
Jellyfin: Home libraries
+
+

And inside the “Movies” library you can see the whole catalog where you can filter or just scroll as well as seeing Suggestions (I think this starts getting populated after a while) and Genres:

+
+Jellyfin: Library catalog options +
Jellyfin: Library catalog options
+
+

Plugins

+

You can also install/activate plugins to get extra features. Most of the plugins you might want to use are already available in the official repositories and can be found in the “Catalog”. There are a lot of plugins that are focused around anime and TV metadata, as well as an Open Subtitles plugin to automatically download missing subtitles (though this is managed with Bazarr).

+

To activate plugins click on the 3 horizontal lines on the top left of the Web UI then navigate to Administration -> Dashboard -> Advanced -> Plugins and click on the Catalog tab (top of the Web UI). Here you can select the plugins you want to install. By default only the official ones are shown, for more you can add more repositories.

+

The only plugin I’m using is the “Playback Reporting”, to get a summary of what is being used in the instance. But I might experiment with some anime-focused plugins when the time comes.

+

Transcoding

+

Although not recommended and explicitly set to not download any x265/HEVC content (by using the Golden rule) there might be cases where the only option you have is to download such content. If that is the case and you happen to have a way to do Hardware Acceleration, for example by having an NVIDIA graphics card (in my case) then you should enable it to avoid using lots of resources on your system.

+

Using hardware acceleration will leverage your GPU to do the transcoding and save resources on your CPU. I tried streaming x265 content and it basically used 70-80% on all cores of my CPU, while on the other hand using my GPU it used the normal amount on the CPU (70-80% on a single core).

+

This will be the steps to install on an NVIDIA graphics card, specifically a GTX 1660 Ti. But more info and guides can be found at Jellyfin: Hardware Acceleration for other acceleration methods.

+
NVIDIA drivers
+

Ensure you have the NVIDIA drivers and utils installed. I’ve you’ve done this in the past then you can skip this part, else you might be using the default nouveau drivers. Follow the next steps to set up the NVIDIA drivers, which basically is a summary of NVIDIA: Installation for my setup, so double check the wiki in case you have an older NVIDIA graphics card.

+

Install the nvidia and nvidia-utils packages:

+
pacman -S nvidia nvidia-utils
+
+

Modify /etc/mkinitcpio.conf to remove kms from the HOOKS array. It should look like this (commented line is how it was for me before the change):

+
...
+# HOOKS=(base udev autodetect modconf kms keyboard keymap consolefont block filesystems fsck)
+HOOKS=(base udev autodetect modconf keyboard keymap consolefont block filesystems fsck)
+...
+
+

Regenerate the initramfs by executing:

+
mkinitcpio -P
+
+

Finally, reboot the system. After the reboot you should be able to check your GPU info and processes being run with the GPU by executing nvidia-smi.

+
Enable hardware acceleration
+

Install from the AUR with yay:

+
yay -S jellyfin-ffmpeg6-bin
+
+

This provides the jellyfin-ffmpeg executable, which is necessary for Jellyfin to do hardware acceleration, it needs to be this specific one.

+

Then in the Jellyfin go to the transcoding settings by clicking on the 3 horizontal lines on the top left of the Web UI and navigating to Administration -> Dashboard -> Playback -> Transcoding and:

+
    +
  • Change the Hardware acceleration from “None” to “Nvidia NVENC”.
  • +
  • Some other options will pop up, just make sure you enable “HEVC” (which is x265) in the list of Enable hardware encoding for:.
  • +
  • Scroll down and specify the ffmpeg path, which is /usr/lib/jellyfin-ffmpeg/ffmpeg.
  • +
+

Don’t forget to click “Save” at the bottom of the Web UI, it will ask if you want to enable hardware acceleration.

+

Bazarr

+

Bazarr is a companion for Sonarr and Radarr that manages and downloads subtitles.

+

Install from the AUR with yay:

+
yay -S bazarr
+
+

Add the bazarr user to the servarr group:

+
gpasswd -a bazarr servarr
+
+

The default port that Bazarr uses is 6767 for http (the one you need for the reverse proxy), and it has pre-configured the default ports for Radarr and Sonarr.

+

Reverse proxy

+

Basically the same as with Radarr: Reverse proxy and Sonarr: Reverse proxy.

+

Add the following setting in the server block of the isos.conf:

+
server {
+    # server_name and other directives
+    ...
+
+    # Increase http2 max sizes
+    large_client_header_buffers 4 16k;
+
+    # some other blocks like location blocks
+    ...
+}
+
+

Then add the following location blocks in the isos.conf, where I’ll keep it as /bazarr/:

+
location /bazarr/ {
+    proxy_pass http://127.0.0.1:6767/bazarr/; # change port if needed
+    proxy_http_version 1.1;
+
+    proxy_set_header X-Real-IP $remote_addr;
+    proxy_set_header Host $http_host;
+    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+    proxy_set_header X-Forwarded-Proto $scheme;
+    proxy_set_header Upgrade $http_upgrade;
+    proxy_set_header Connection "Upgrade";
+
+    proxy_redirect off;
+}
+# Allow the Bazarr API through if you enable Auth on the block above
+location /bazarr/api {
+    auth_request off;
+    proxy_pass http://127.0.0.1:6767/bazarr/api;
+}
+
+

This is taken from Bazarr: Reverse proxy help. Restart the nginx service for the changes to take effect:

+
systemctl restart nginx.service
+
+

Start using Bazarr

+

You can now start/enable the bazarr.service if you haven’t already:

+
systemctl start bazarr.service
+systemctl enable bazarr.service
+
+

This will start the service and create the default configs under /var/lib/bazarr. You need to change the base_url for the necessary services as they’re running under a reverse proxy and under subdirectories. Edit /var/lib/bazarr/config/config.ini:

+
[general]
+port = 6767
+base_url = /bazarr
+
+[sonarr]
+port = 8989
+base_url = /sonarr
+
+[radarr]
+port = 7878
+base_url = /radarr
+
+

Then restart the bazarr service:

+
systemctl restart bazarr.service
+
+

Now https://isos.yourdomain.com/bazarr is accessible. Secure the instance right away by adding authentication under Settings -> General -> Security. I added the “Forms” option, just fill in the username and password then click on save changes on the top left of the page. You can restart the service again and check that it asks for login credentials. I also disabled Settings -> General -> Updates -> Automatic.

+

Configuration

+

Will be following the official Bazarr: Setup guide as well as the recommendations by TRaSH: Bazarr.

+

Anything that is not mentioned in either guide or that is specific to how I’m setting up stuff will be stated below.

+
Providers
+

This doesn’t require much thinking and its up to personal preference, but I’ll list the ones I added:

+
    +
  • OpenSubtitles.com: requires an account (the .org option is deprecated).
      +
    • For a free account it only lets you download around 20 subtitles per day, and they contain ads. You could pay for a VIP account ($3 per month) and that will give you 1000 subtitles per day and no ads. But if you’re fine with 20 ads per day you can try to get rid of the ads by running an automated script. Such option can be found at brianspilner01/media-server-scripts: sub-clean.sh.
    • +
    +
  • +
  • YIFY Subtitles
  • +
  • Subscenter
  • +
  • Supersubtitles
  • +
  • TVSubtitles
  • +
  • Subtitulamos.tv: Spanish subtitles provider.
  • +
  • Argenteam: LATAM Spanish subtitles provider.
  • +
  • Subdivx: LATAM Spanish / Spanish subtitles provider.
  • +
+

I’ve tested this setup for the following languages (with all default settings as stated in the guides):

+
    +
  • English
  • +
  • Spanish
  • +
+

I tried with “Latin American Spanish” but they’re hard to find, those two work pretty good.

+

None of these require an Anti-Captcha account (which is a paid service), but I created one anyways in case I need it. Though you need to add credits to it (pretty cheap though) if you ever use it.

]]>
+
+ + Set up qBitTorrent with Jackett for use with Starr apps + https://blog.luevano.xyz/a/torrenting_with_qbittorrent.html + https://blog.luevano.xyz/a/torrenting_with_qbittorrent.html + Mon, 24 Jul 2023 02:06:24 GMT + Code + English + Server + Tools + Tutorial + How to set up a torrenting solution with qBitTorrent in preparation for a media server with Jellyfin and Starr apps, on Arch. With Jackett and flaresolverr, too. + Riding on my excitement of having a good internet connection and having setup my home server now it’s time to self host a media server for movies, series and anime. I’ll setup qBitTorrent as the downloader, Jackett for the trackers, the Starr apps for the automatic downloading and Jellyfin as the media server manager/media viewer. This was going to be a single entry but it ended up being a really long one so I’m splitting it, this being the first part.

+

I’ll be exposing my stuff on a subdomain only so I can access it while out of home and for SSL certificates (not required), but shouldn’t be necessary and instead you can use a VPN (how to set up). For your reference, whenever I say “Starr apps” (*arr apps) I mean the family of apps such as Sonarr, Radarr, Bazarr, Readarr, Lidarr, etc..

+

Most of my config is based on the TRaSH-Guides (will be mentioned as “TRaSH” going forward). Specially get familiar with the TRaSH: Native folder structure and with the TRaSH: Hardlinks and instant moves. Will also use the default configurations based on the respective documentation for each Starr app and service, except when stated otherwise.

+

Everything here is performed in arch btw and all commands should be run as root unless stated otherwise.

+

Kindly note that I do not condone the use of torrenting for illegal activities. I take no responsibility for what you do when setting up anything shown here. It is for you to check your local laws before using automated downloaders such as Sonarr and Radarr.

+

Table of contents

+ +

Prerequisites

+

The specific programs are mostly recommendations, if you’re familiar with something else or want to change things around, feel free to do so but everything will be written with them in mind.

+

If you want to expose to a (sub)domain, then similar to my early tutorial entries (specially the website for the reverse proxy plus certificates):

+
    +
  • nginx for the reverse proxy.
  • +
  • certbot for the SSL certificates.
  • +
  • ufw for the firewall.
  • +
  • yay to install AUR packages. +
  • +
  • An A (and/or AAAA) or a CNAME for isos (or whatever you want to call it).
      +
    • For automation software (qBitTorrent, Jackett, Starr apps, etc.). One subdomain per service can be used instead.
    • +
    +
  • +
+

Note: I’m using the explicit 127.0.0.1 ip instead of localhost in the reverse proxies/services config as localhost resolves to ipv6 sometimes which is not configured on my server correctly. If you have it configured you can use localhost without any issue.

+

Directory structure

+

Basically following TRaSH: Native folder structure except for the directory permissions part, I’ll do the same as with my Komga setup guide to stablish default group permissions.

+

The desired behaviour is: set servarr as group ownership, set write access to group and whenever a new directory/file is created, inherit these permission settings. servarr is going to be a service user and I’ll use the root of a mounted drive at /mnt/a.

+
    +
  1. Create a service user called servarr (it could just be a group, too):
  2. +
+
useradd -r -s /usr/bin/nologin -M -c "Servarr applications" servarr
+
+
    +
  1. Create the torrents directory and set default permissions:
  2. +
+
cd /mnt/a # change this according to your setup
+mkdir torrents
+chown servarr:servarr torrents
+chmod g+w torrents
+chmod g+s torrents
+setfacl -d -m g::rwx torrents
+setfacl -d -m o::rx torrents
+
+
    +
  1. Check that the permissions are set correctly (getfacl torrents)
  2. +
+
# file: torrents/
+# owner: servarr
+# group: servarr
+# flags: -s-
+user::rwx
+group::rwx
+other::r-x
+default:user::rwx
+default:group::rwx
+default:other::r-x
+
+
    +
  1. Create the subdirectories you want with any user (I’ll be using servarr personally):
  2. +
+
mkdir torrents/{tv,movies,anime}
+chown -R servarr: torrents
+
+
    +
  1. Finally repeat steps 2 - 4 for the media directory.
  2. +
+

The final directory structure should be the following:

+
root_dir
+├── torrents
+│   ├── movies
+│   ├── music
+│   └── tv
+└── media
+    ├── movies
+    ├── music
+    └── tv
+
+

Where root_dir is /mnt/a in my case. This is going to be the reference for the following applications set up.

+

Later, add the necessary users to the servarr group if they need write access, by executing:

+
gpasswd -a <USER> servarr
+
+

Jackett

+

Jackett is a “proxy server” (or “middle-ware”) that translates queries from apps (such as the Starr apps in this case) into tracker-specific http queries. Note that there is an alternative called Prowlarr that is better integrated with most if not all Starr apps, requiring less maintenance; I’ll still be sticking with Jackett, though.

+

Install from the AUR with yay:

+
yay -S jackett
+
+

I’ll be using the default 9117 port, but change accordingly if you decide on another one.

+

Reverse proxy

+

I’m going to have most of the services under the same subdomain, with different subdirectories. Create the config file isos.conf at the usual sites-available/enabled path for nginx:

+
server {
+    listen 80;
+    server_name isos.yourdomain.com;
+
+    location /jack { # you can change this to jackett or anything you'd like, but it has to match the jackett config on the next steps
+        proxy_pass http://127.0.0.1:9117; # change the port according to what you want
+
+        proxy_set_header X-Real-IP $remote_addr;
+        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+        proxy_set_header X-Forwarded-Proto $scheme;
+        proxy_set_header X-Forwarded-Host $http_host;
+        proxy_redirect off;
+    }
+}
+
+

This is the basic reverse proxy config as shown in Jackett: Running Jackett behind a reverse proxy. The rest of the services will be added under different location block on their respective steps.

+

SSL certificate

+

Create/extend the certificate by running:

+
certbot --nginx
+
+

That will automatically detect the new subdomain config and create/extend your existing certificate(s). Restart the nginx service for changes to take effect:

+
systemctl restart nginx.service
+
+

Start using Jackett

+

You can now start/enable the jackett.service:

+
systemctl enable jackett.service
+systemctl start jackett.service
+
+

It will autocreate the default configuration under /var/lib/jackett/ServerConfig.json, which you need to edit at least to change the BasePathOverride to match what you used in the nginx config:

+
{
+    "Port": 9117,
+    "SomeOtherConfigs": "some_other_values",
+    "BasePathOverride": "/jack",
+    "MoreConfigs": "more_values",
+}
+
+

Also modify the Port if you changed it. Restart the jackett service:

+
systemctl restart jackett.service
+
+

It should now be available at https://isos.yourdomain.com/jack. Add an admin password right away by scroll down and until the first config setting; don’t forget to click on “Set Password”. Change any other config you want from the Web UI, too (you’ll need to click on the blue “Apply server settings” button).

+

Note that you need to set the “Base URL override” to http://127.0.0.1:9117 (or whatever port you used) so that the “Copy Torznab Feed” button works for each indexer.

+

Indexers

+

For Jackett, an indexer is just a configured tracker for some of the commonly known torrent sites. Jackett comes with a lot of pre-configured public and private indexers which usually have multiple URLs (mirrors) per indexer, useful when the main torrent site is down. Some indexers come with extra features/configuration depending on what the site specializes on.

+

To add an indexer click on the “+ Add Indexer” at the top of the Web UI and look for indexers you want, then click on the “+” icon on the far-most right for each indexer or select the ones you want (clicking on the checkbox on the far-most left of the indexer) and scroll all the way to the bottom to click on “Add Selected”. They then will show as a list with some available actions such as “Copy RSS Feed”, “Copy Torznab Feed”, “Copy Potato Feed”, a button to search, configure, delete and test the indexer, as shown below:

+
+Jacket: configured indexers +
Jackett: configured indexers
+
+

You can manually test the indexers by doing a basic search to see if they return anything, either by searching on each individual indexer by clicking on the magnifying glass icon on the right of the indexer or clicking on “Manual Search” button which is next to the “+ Add Indexer” button at the top right.

+

Explore each indexer’s configuration in case there is stuff you might want to change.

+

FlareSolverr

+

FlareSolverr is used to bypass certain protection that some torrent sites have. This is not 100% necessary and only needed for some trackers sometimes, it also doesn’t work 100%.

+

You could install from the AUR with yay:

+
yay -S flaresolverr-bin
+
+

At the time of writing, the flaresolverr package didn’t work for me because of python-selenium. flaresolverr-bin was updated around the time I was writing this, so that is what I’m using and what’s working fine so far, it contains almost everything needed (it has self contained libraries) except for xfvb.

+

Install dependencies via pacman:

+
pacman -S xorg-server-xvfb
+
+

You can now start/enable the flaresolverr.service:

+
systemctl enable flaresolverr.service
+systemctl start flaresolverr.service
+
+

Verify that the service started correctly by checking the logs:

+
journalctl -fxeu flaresolverr
+
+

It should show “Test successful” and “Serving on http://0.0.0.0:8191” (which is the default). Jackett now needs to be configured by adding http://127.0.0.1:8191 almost at the end in the “FlareSolverr API URL” field, then click on the blue “Apply server settings” button at the beginning of the config section. This doesn’t need to be exposed or anything, it’s just an internal API that Jackett (or anything you want) will use.

+

qBitTorrent

+

qBitTorrent is a fast, stable and light BitTorrent client that comes with many features and in my opinion it’s a really user friendly client and my personal choice for years now. But you can choose whatever client you want, there are more lightweight alternatives such as Transmission.

+

Install the qbittorrent-nox package (“nox” as in “no X server”):

+
pacman -S qbittorrent-nox
+
+

By default the package doesn’t create any (service) user, but it is recommended to have one so you can run the service under it. Create the user, I’ll call it qbittorrent and leave it with the default homedir (/home):

+
useradd -r -m qbittorrent
+
+

Add the qbittorrent user to the servarr group:

+
gpasswd -a qbittorrent servarr
+
+

Decide a port number you’re going to run the service on for the next steps, the default is 8080 but I’ll use 30000; it doesn’t matter much, as long as it matches for all the config. This is the qbittorrent service port, it is used to connect to the instance itself through the Web UI or via API, you also need to open a port for listening to peer connections. Choose any port you want, for example 50000 and open it with your firewall, ufw in my case:

+
ufw allow 50000/tcp comment "qBitTorrent - Listening port"
+
+

Reverse proxy

+

Add the following location block into the isos.conf with whatever subdirectory name you want, I’ll call it qbt:

+
location /qbt/ {
+    proxy_pass http://localhost:30000/; # change port to whatever number you want
+    proxy_http_version 1.1;
+
+    proxy_set_header Host $host;
+    proxy_set_header X-Forwarded-Host $http_host;
+    proxy_set_header X-Forwarded-For $remote_addr;
+
+    proxy_cookie_path / "/; Secure";
+    proxy_read_timeout 600s;
+    proxy_send_timeout 600s;
+}
+
+

This is taken from qBitTorrent: Nginx reverse proxy for Web UI. Restart the nginx service for the changes to take effect:

+
systemctl restart nginx.service
+
+

Start using qBitTorrent

+

You can now start/enable the qbittorrent-nox@.service using the service account created (qbittorrent):

+
systemctl enable `qbittorrent-nox@qbittorrent.service
+systemctl start `qbittorrent-nox@qbittorrent.service
+
+

This will start qbittorrent using default config. You need to change the port (in my case to 30000) and set qbittorrent to restart on exit (the Web UI has a close button). I guess this can be done before enabling/starting the service, but either way let’s create a “drop-in” file by “editing” the service:

+
systemctl edit `qbittorrent-nox@qbittorrent.service
+
+

Which will bring up a file editing mode containing the service unit and a space where you can add/override anything, add:

+
[Service]
+Environment="QBT_WEBUI_PORT=30000" # or whatever port number you want
+Restart=on-success
+RestartSec=5s
+
+

When exiting from the file (if you wrote anything) it will create the override config. Restart the service for changes to take effect (you might be asked to reload the systemd daemon):

+
systemctl restart `qbittorrent-nox@qbittorrent.service
+
+

You can now head to https://isos.yourdomain.com/qbt/ and login with user admin and password adminadmin (by default). Change the default password right away by going to Tools -> Options -> Web UI -> Authentication. The Web UI is basically the same as the normal desktop UI so if you’ve used it it will feel familiar. From here you can threat it as a normal torrent client and even start using for other stuff other than the specified here.

+

Configuration

+

It should be usable already but you can go further and fine tune it, specially to some kind of “convention” as shown in TRaSH: qBitTorrent basic setup and subsequent qbittorrent guides.

+

I use all the suggested settings by TRaSH, where the only “changes” are for personal paths, ports, and in general connection settings that depend on my setup. The only super important setting I noticed that can affect our setup (meaning what is described in this entry) is the Web UI -> Authentication for the “Bypass authentication for clients on localhost”. This will be an issue because the reverse proxy is accessing qbittorrent via localhost, so this will make the service open to the world, experiment at your own risk.

+

Finally, add categories by following TRaSH: qBitTorrent how to add categories, basically right clicking on Categories -> All (x) (located at the left of the Web UI) and then on “Add category”; I use the same “Category” and “Save Path” (tv and tv, for example), where the “Save Path” will be a subdirectory of the configured global directory for torrents (TRaSH: qBitTorent paths and categories breakdown). I added 3: tv, movies and anime.

+

Trackers

+

Often some of the trackers that come with torrents are dead or just don’t work. You have the option to add extra trackers to torrents either by:

+
    +
  • Automatically add a predefined list on new torrents: configure at Tools -> Options -> BitTorrent, enable the last option “Automatically add these trackers to new downloads” then add the list of trackers. This should only be done on public torrents as private ones might ban you or something.
  • +
  • Manually add a list of trackers to individual torrents: configure by selecting a torrent, clicking on Trackers on the bottom of the Web UI, right clicking on an empty space and selecting “Add trackers…” then add the list of trackers.
  • +
+

On both options, the list of trackers need to have at least one new line in between each new tracker. You can find trackers from the following sources:

+ +

Both sources maintain an updated list of trackers. You also might need to enable an advanced option so all the new trackers are contacted (Only first tracker contacted): configure at Tools -> Options -> Advanced -> libtorrent Section and enable both “Always announce to all tiers” and “Always announce to all trackers in a tier”.

]]>
+
Configure system logs on Arch to avoid filled up disk https://blog.luevano.xyz/a/arch_logs_flooding_disk.html @@ -79,6 +886,7 @@ LogNamespace=email How to set up a manga server with Komga as media server and mangal for downloading manga, on Arch. Tachiyomi integration is available thanks to Komga. I’ve been wanting to set up a manga media server to hoard some mangas/comics and access them via Tachiyomi, but I didn’t have enough space in my vultr VPS. Now that I have symmetric fiber optic at home and my spare PC to use as a server I decided to go ahead and create one. As always, i use arch btw so these instructions are specifically for it, I’m not sure how easier/harder it is for other distros, I’m just too comfortable with arch honestly.

I’m going to run it as an exposed service using a subdomain of my own, so the steps are taking that into account, if you want to run it locally (or on a LAN/VPN) then it is going to be easier/with less steps (you’re on your own). Also, as you might notice I don’t like to use D*ck*r images or anything (ew).

+

At the time of editing this entry (06-28-2023) Komga has already upgraded to v.1.0.0 and it introduces some breaking changes if you already had your instance set up. Read more here. The only change I did here was changing the port to the new default.

As always, all commands are run as root unless stated otherwise.

Table of contents

@@ -353,7 +1161,7 @@ Dandadan|0110|110|Mangapill

This komga package creates a komga (service) user and group which is tied to the also included komga.service.

Configure it by editing /etc/komga.conf:

-
SERVER_PORT=8989
+
SERVER_PORT=25600
 SERVER_SERVLET_CONTEXT_PATH=/ # this depends a lot of how it's going to be served (domain, subdomain, ip, etc)
 
 KOMGA_LIBRARIES_SCAN_CRON="0 0 * * * ?"
@@ -369,7 +1177,6 @@ KOMGA_DATABASE_BACKUP_SCHEDULE="0 0 */8 * * ?"
 

My changes (shown above):

    -
  • Port on 8989 because 8080 its too generic.
  • cron schedules.
    • It’s not actually cron but rather a cron-like syntax used by Spring as stated in the Komga config.
    @@ -385,7 +1192,8 @@ KOMGA_DATABASE_BACKUP_SCHEDULE="0 0 */8 * * ?" server_name komga.yourdomain.com; # change accordingly to your wanted subdomain and domain name location / { - proxy_pass http://localhost:8989; # change 8989 to the port you want to use + proxy_pass http://localhost:25600; # change port if needed + proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; @@ -600,7 +1408,7 @@ default:other::r-x

    Other than that I used few key sprites from vryell: Controller & Keyboard Icons and a font from datagoblin: Monogram.

    The snake

    This is the most challenging part in my opinion as making all the body parts follow the head in a user defined path it’s kinda hard. I tried with like 4-5 options and the one I’m detailing here is the only one that worked as I wanted for me. This time the directory structure I’m using is the following:

    -
    +
    FileSystem - Snake dir structure
    FileSystem - Snake dir structure
    @@ -634,7 +1442,7 @@ func _rotate_to(direction: int) -> void: _direction = _direction.rotated(deg2rad(direction * Global.SNAKE_ROT_SPEED * get_physics_process_delta_time()))

After tunning all the necessary parameters you should get something like this:

-
+
Snake - Basic movement (left and right controls)
Snake - Basic movement (left and right controls)
@@ -671,7 +1479,7 @@ func _on_Head_snake_path_new_point(coordinates: Vector2) -> void: update()

With this, we’re now populating the Path2D curve points with the position of the snake head. You should be able to see it because of the _draw call. If you run it you should see something like this:

-
+
Snake - Basic movement with path
Snake - Basic movement with path
@@ -715,7 +1523,7 @@ func _on_Head_snake_path_new_point(coordinates: Vector2) -> void: _add_initial_segment(TAIL_SEGMENT_NP)

Select the Snake node and add the Body and Tail scene to the parameters, respectively. Then when running you should see something like this:

-
+
Snake - Basic movement with all body parts
Snake - Basic movement with all body parts
@@ -758,7 +1566,7 @@ func _add_segment_to_queue() -> void: body_segment_queue.append(body_segment_queue.back() + Global.SNAKE_SEGMENT_SIZE)

With everything implemented and connected accordingly then we can add segments on demand (for testing I’m adding with a key press), it should look like this:

-
+
Snake - Basic movement with dynamic addition of new segments
Snake - Basic movement with dynamic addition of new segments
@@ -821,21 +1629,21 @@ func _on_body_entered(body: Node) -> void: add_child(food)

And this is used in _process to place new food whenever needed. For now I added a condition to add food until 10 pieces are in place, and keep adding whenever the food is is lower than 10. After setting everything up, this is the result:

-
+
Snake - Food basic interaction
Snake - Food basic interaction

Za warudo! (The world)

It just happend that I saw a video to create random maps by using a method called random walks, this video was made by NAD LABS: Nuclear Throne Like Map Generation In Godot. It’s a pretty simple but powerful script, he provided the source code from which I based my random walker, just tweaked a few things and added others. Some of the maps than can be generated with this method (already aded some random sprites):

-
+
World map generator - Random map 1
World map generator - Random map 1
-
+
World map generator - Random map 2
World map generator - Random map 2
-
+
World map generator - Random map 3
World map generator - Random map 3
@@ -1258,35 +2066,35 @@ func physics_process(delta: float) -> void:

Config

Default import settings

Since this is just pixel art, the importing settings for textures needs to be adjusted so the sprites don’t look blurry. Go to Project -> Project settings… -> Import defaults and on the drop down select Texture, untick everything and make sure Compress/Mode is set to Lossless.

-
+
Project settings - Import defaults - Texture settings
Project settings - Import defaults - Texture settings

General settings

It’s also a good idea to setup some config variables project-wide. To do so, go to Project -> Project settings… -> General, select Application/config and add a new property (there is a text box at the top of the project settings window) for game scale: application/config/game_scale for the type use float and then click on add; configure the new property to 3.0; On the same window, also add application/config/version as a string, and make it 1.0.0 (or whatever number you want).

-
+
Project settings - General - Game scale and version properties
Project settings - General - Game scale and version properties

For my personal preferences, also disable some of the GDScript debug warnings that are annoying, this is done at Project -> Project settings… -> General, select Debug/GDScript and toggle off Unused arguments, Unused signal and Return value discarded, and any other that might come up too often and don’t want to see.

-
+
Project settings - General - GDScript debug warnings
Project settings - General - GDScript debug warnings

Finally, set the initial window size in Project -> Project settings… -> General, select Display/Window and set Size/Width and Size/Height to 600 and 800, respectively. As well as the Stretch/Mode to viewport , and Stretch/Aspect to keep:

-
+
Project settings - General - Initial window size
Project settings - General - Initial window size

Keybindings

I only used 3 actions (keybindings): jump, restart and toggle_debug (optional). To add custom keybindings (so that the Input.something() API can be used), go to Project -> Project settings… -> Input Map and on the text box write jump and click add, then it will be added to the list and it’s just a matter of clicking the + sign to add a Physical key, press any key you want to be used to jump and click ok. Do the same for the rest of the actions.

-
+
Project settings - Input Map - Adding necessary keybindings
Project settings - Input Map - Adding necessary keybindings

Layers

Finally, rename the physics layers so we don’t lose track of which layer is which. Go to Project -> Layer Names -> 2d Physics and change the first 5 layer names to (in order): player, ground, pipe, ceiling and score.

-
+
Project settings - Layer Names - 2D Physics
Project settings - Layer Names - 2D Physics
@@ -1295,12 +2103,12 @@ func physics_process(delta: float) -> void:

Importing

Create the necessary directories to hold the respective assets and it’s just a matter of dragging and dropping, I used directories: res://entities/actors/player/sprites/, res://fonts/, res://levels/world/background/sprites/, res://levels/world/ground/sprites/, res://levels/world/pipe/sprites/, res://sfx/. For the player sprites, the FileSystem window looks like this (entities/actor directories are really not necessary):

-
+
FileSystem - Player sprite imports
FileSystem - Player sprite imports

It should look similar for other directories, except maybe for the file extensions. For example, for the sfx:

-
+
FileSystem - SFX imports
FileSystem - SFX imports
@@ -1308,72 +2116,72 @@ func physics_process(delta: float) -> void:

Now it’s time to actually create the game, by creating the basic scenes that will make up the game. The hardest part and the most confusing is going to be the TileMaps, so that goes first.

TileMaps

I’m using a scene called WorldTiles with a Node2D node as root called the same. With 2 different TileMap nodes as children named GroundTileMap and PipeTileMap (these are their own scene); yes 2 different TileMaps because we need 2 different physics colliders (in Godot 4.0 you can have a single TileMap with different physics colliders in it). Each node has its own script. It should look something like this:

-
+
Scene - WorldTiles (TileMaps)
Scene - WorldTiles (TileMaps)

I used the following directory structure:

-
+
Scene - WorldTiles - Directory structure
Scene - WorldTiles - Directory structure

To configure the GroundTileMap, select the node and click on (empty) on the TileMap/Tile set property and then click on New TileSet, then click where the (empty) used to be, a new window should open on the bottom:

-
+
TileSet - Configuration window
TileSet - Configuration window

Click on the plus on the bottom left and you can now select the specific tile set to use. Now click on the yellow + New Single Tile, activate the grid and select any of the tiles. Should look like this:

-
+
TileSet - New single tile
TileSet - New single tile

We need to do this because for some reason we can’t change the snap options before selecting a tile. After selecting a random tile, set up the Snap Options/Step (in the Inspector) and set it to 16x16 (or if using a different tile set, to it’s tile size):

-
+
TileSet - Tile - Step snap options
TileSet - Tile - Step snap options

Now you can select the actual single tile. Once selected click on Collision, use the rectangle tool and draw the rectangle corresponding to that tile’s collision:

-
+
TileSet - Tile - Selection and collision
TileSet - Tile - Selection and collision

Do the same for the other 3 tiles. If you select the TileMap itself again, it should look like this on the right (on default layout it’s on the left of the Inspector):

-
+
TileSet - Available tiles
TileSet - Available tiles

The ordering is important only for the “underground tile”, which is the filler ground, it should be at the end (index 3); if this is not the case, repeat the process (it’s possible to rearrange them but it’s hard to explain as it’s pretty weird).

At this point the tilemap doesn’t have any physics and the cell size is wrong. Select the GroundTileMap, set the TileMap/Cell/Size to 16x16, the TileMap/Collision/Layer set to bit 2 only (ground layer) and disable any TileMap/Collision/Mask bits. Should look something like this:

-
+
TileMap - Cell size and collision configuration
TileMap - Cell size and collision configuration

Now it’s just a matter of repeating the same for the pipes (PipeTileMap), only difference is that when selecting the tiles you need to select 2 tiles, as the pipe is 2 tiles wide, or just set the Snap Options/Step to 32x16, for example, just keep the cell size to 16x16.

Default ground tiles

I added few default ground tiles to the scene, just for testing purposes but I left them there. These could be place programatically, but I was too lazy to change things. On the WorldTiles scene, while selecting the GroundTileMap, you can select the tiles you want to paint with, and left click in the grid to paint with the selected tile. Need to place tiles from (-8, 7) to (10, 7) as well as the tile below with the filler ground (the tile position/coordinates show at the bottom left, refer to the image below):

-
+
Scene - WorldTiles - Default ground tiles
Scene - WorldTiles - Default ground tiles

Player

On a new scene called Player with a KinematicBody2D node named Player as the root of the scene, then for the children: AnimatedSprite as Sprite, CollisionShape2D as Collision (with a circle shape) and 3 AudioStreamPlayers for JumpSound, DeadSound and HitSound. Not sure if it’s a good practice to have the audio here, since I did that at the end, pretty lazy. Then, attach a script to the Player node and then it should look like this:

-
+
Scene - Player - Node setup
Scene - Player - Node setup

Select the Player node and set the CollisionShape2D/Collision/Layer to 1 and the CollisionObject2D/Collision/Mask to 2 and 3 (ground and pipe).

For the Sprite node, when selecting it click on the (empty) for the AnimatedSprite/Frames property and click New SpriteFrames, click again where the (empty) used to be and ane window should open on the bottom:

-
+
Scene - Player - SpriteFrames window
Scene - Player - SpriteFrames window

Right off the bat, set the Speed to 10 FPS (bottom left) and rename default to bird_1. With the bird_1 selected, click on the Add frames from a Sprite Sheet, which is the second button under Animation Frames: which looks has an icon of a small grid (next to the folder icon), a new window will popup where you need to select the respective sprite sheet to use and configure it for importing. On the Select Frames window, change the Vertical to 1, and then select all 4 frames (Ctrl + Scroll wheel to zoom in):

-
+
Scene - Player - Sprite sheet importer
Scene - Player - Sprite sheet importer

After that, the SpriteFrames window should look like this:

-
+
Scene - Player - SpriteFrames window with sprite sheet configured
Scene - Player - SpriteFrames window with sprite sheet configured
@@ -1392,12 +2200,12 @@ func physics_process(delta: float) -> void:

Game

This is the actual Game scene that holds all the playable stuff, here we will drop in all the previous scenes; the root node is a Node2D and also has an attached script. Also need to add 2 additional AudioStreamPlayers for the “start” and “score” sounds, as well as a Sprite for the background (Sprite/Offset/Offset set to (0, 10)) and a Camera2D (Camera2D/Current set to true (checked)). It should look something like this:

-
+
Scene - Game - Node setup
Scene - Game - Node setup

The scene viewport should look something like the following:

-
+
Scene - Game - Viewport
Scene - Game - Viewport
@@ -1405,12 +2213,12 @@ func physics_process(delta: float) -> void:

Fonts

We need some font Resources to style the Label fonts. Under the FileSystem window, right click on the fonts directory (create one if needed) and click on New Resource... and select DynamicFontData, save it in the “fonts” directory as SilverDynamicFontData.tres (Silver as it is the font I’m using) then double click the just created resource and set the DynamicFontData/Font Path to the actual Silver.ttf font (or whatever you want).

Then create a new resource and this time select DynamicFont, name it SilverDynamicFont.tres, then double click to edit and add the SilverDynamicFontData.tres to the DynamicFont/Font/Font Data property (and I personally toggled off the DynamicFont/Font/Antialiased property), now just set the DynamicFont/Settings/(Size, Outline Size, Outline Color) to 32, 1 and black, respectively (or any other values you want). It should look something like this:

-
+
Resource - DynamicFont - Default font
Resource - DynamicFont - Default font

Do the same for another DynamicFont which will be used for the score label, named SilverScoreDynamicFont.tres. Only changes are Dynamic/Settings/(Size, Outline Size) which are set to 128 and 2, respectively. The final files for the fonts should look something like this:

-
+
Resource - Dynamicfont - Directory structure
Resource - Dynamicfont - Directory structure
@@ -1439,7 +2247,7 @@ func physics_process(delta: float) -> void:

The scene ends up looking like this:

-
+
Scene - UI - Node setup
Scene - UI - Node setup
@@ -1573,7 +2381,7 @@ func _remove_first_ground() -> void:

Where you might notice that the _initial_new_tile_x is 11, instead of 10, refer to Default ground tiles where we placed tiles from -8 to 10, so the next empty one is 11. These _place_new_ground and _remove_first_ground functions are called upon receiving the signal.

PipeTileMap

This is really similar to the GroundTileMap code, instead of defining an enum for the ground tiles, we define it for the pipe patterns (because each pipe is composed of multiple pipe tiles). If your pipe tile set looks like this (notice the index):

-
+
PipeTileMap - Tile set indexes
PipeTileMap - Tile set indexes
@@ -1675,7 +2483,7 @@ func get_high_score() -> int: save_data()

Now, this script in particular will need to be a Singleton (AutoLoad), which means that there will be only one instance and will be available across all scripts. To do so, go to Project -> Project settings… -> AutoLoad and select this script in the Path: and add a Node Name: (I used SavedData, if you use something else, be careful while following this devlog) which will be the name we’ll use to access the singleton. Toggle on Enable if needed, it should look like this:

-
+
Project settings - AutoLoad - SavedData singleton
Project settings - AutoLoad - SavedData singleton
@@ -3451,8 +4259,8 @@ systemctl enable spamassassin.service
  • Password: your user password (as in the password you use to login to the server with that user)
  • All that’s left to do is test your mail server for spoofing, and to see if everything is setup correctly. Go to DKIM Test and follow the instructions (basically click next, and send an email with whatever content to the email that they provide). After you send the email, you should see something like:

    -
    -DKIM Test successful +
    +DKIM Test successful
    DKIM Test successful
    ]]> @@ -3500,8 +4308,8 @@ systemctl enable nginx.service systemctl start nginx.service

    And that’s it, at this point you can already look at the default initial page of Nginx if you enter the IP of your server in a web browser. You should see something like this:

    -
    -Nginx welcome page +
    +Nginx welcome page
    Nginx welcome page

    As stated in the welcome page, configuration is needed, head to the directory of Nginx:

    @@ -3567,8 +4375,8 @@ cd sites-available systemctl restart nginx

    If everything goes correctly, you can now go to your website by typing domain.name on a web browser. But you will see a “404 Not Found” page like the following (maybe with different Nginx version):

    -
    -Nginx 404 Not Found page +
    +Nginx 404 Not Found page
    Nginx 404 Not Found page

    That’s no problem, because it means that the web server it’s actually working. Just add an index.html file with something simple to see it in action (in the /var/www/some_folder that you decided upon). If you keep seeing the 404 page make sure your root line is correct and that the directory/index file exists.

    -- cgit v1.2.3-70-g09d2