selfhosted music server guide added

This commit is contained in:
2005 2024-07-15 20:55:29 +02:00
parent 770038eb1c
commit 4388b9607d
28 changed files with 387 additions and 33 deletions

1
assets/icons/code.svg Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-code"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M7 8l-4 4l4 4" /><path d="M17 8l4 4l-4 4" /><path d="M14 4l-4 16" /></svg>

After

Width:  |  Height:  |  Size: 388 B

View file

@ -4,7 +4,8 @@ favicon = "/favicon.png"
[footer] [footer]
since = 2024 since = 2024
customText = "Colorscheme based on Shades of Purple" customText = "Art by byung jun ko"
customTextUrl= "https://www.behance.net/gallery/111899291/Blue-Spring-2019"
[dateFormat] [dateFormat]
published = "Jan 02, 2006" published = "Jan 02, 2006"

View file

@ -4,7 +4,6 @@ date: 2022-03-06
layout: "archives" layout: "archives"
menu: menu:
main: main:
weight: 2
params: params:
icon: archives icon: archives
--- ---

View file

@ -4,7 +4,6 @@ date: 2022-03-06
layout: "archives" layout: "archives"
menu: menu:
main: main:
weight: 2
params: params:
icon: archives icon: archives
--- ---

View file

@ -5,7 +5,6 @@ layout: "archives"
slug: "archives" slug: "archives"
menu: menu:
main: main:
weight: 2
params: params:
icon: archives icon: archives
--- ---

View file

@ -88,7 +88,9 @@ Any issues with the services shall be discussed on the [dedicated matrix channel
**You are free to use mine anytime free of charge.** **You are free to use mine anytime free of charge.**
A plan on hosting **every** frontend that Libredirect has. I will also make them available via I2P sometime in the future. A plan on hosting **every** frontend that Libredirect has. I will also make them available via I2P, Tor and lokinet sometime in the future.
[If you're interested in reviewing my privacy [If you're interested in reviewing my privacy
terms, they are available here.](/privacy-policy) terms, they are available here.](/privacy-policy)
This below is not the full list, if you want all the details go and look at my [infrastructure repo containing them all](https://git.4o1x5.dev/4o1x5/infrastructure/#Privacy-respecting-services)

View file

@ -2,10 +2,9 @@
title: "Livestream" title: "Livestream"
date: 2024-04-28 date: 2024-04-28
edited: 2024-04-28 edited: 2024-04-28
draft: false draft: true
menu: menu:
main: main:
weight: 2
params: params:
icon: cast icon: cast
--- ---

View file

@ -0,0 +1,15 @@
---
title: "Projects"
date: 2024-05-31
edited: 2024-05-31
draft: true
menu:
main:
weight: 2
params:
icon: code
layout: "projects"
---
my projects

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 975 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 163 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 161 KiB

View file

@ -0,0 +1,218 @@
---
title: Ditch spotify, make your own
description: Stream music from your local jellyfin server
date: 2024-07-15 07:00:00+0000
image: feishin.png
categories:
- Nix
- Piracy
tags:
- Jellyfin
- Music
- Homelab
- Selfhost
draft: false
writingTime: "1h 40m"
---
## Introduction
I have ditched all kind of subscription based services as of 2024. Spotify was one of my last subscriptions I cancelled and I have migrated to listening offline, then to online via my jellyfin server. I mainly listen to high-bitrate flac music that I pirate from sources like [soulseek](https://wl.vern.cc/wiki/Soulseek?lang=en). I have a collection of about 1000 music from 500 different artists.
I download flacs only to make my self feel better by saying I listen to HQ music but in reality I probably don't hear the difference between a 128kb compressed MP3 and a 1440kb ripped Flac. I also have a entry level [KZ ZS10 IEM](https://kz-audio.com/kz-zs10-pro.html) that I use with my on-board audio driver. I am also a based bass enjoyer, so all I really need is sub frequencies...
## Why pirate?
My main reason is privacy. I have yet to found a platform that respects my privacy and allows me to buy any kind of albums/songs with Bitcoin or Monero, therefore my last resort is to pirate it. I could buy the original CD's but most artists I listen to don't have one, and I loath ripping.
Everyone has their own opinion about piracy, and I think in my case it's a 100% justified.
## Jellyfin
_Jellyfin is a Free Software Media System that puts you in control of managing and streaming your media. It is an alternative to the proprietary Emby and Plex, to provide media from a dedicated server to end-user devices via multiple apps._
Jellyfin is a really great mediaserver, It has many clients and supports almost any kind of media, ranging from visual to audible.
I have been using it for about two years now, but recently I just realized I could stream my music from there instead of syncing my pirated music to all my devices. For the past few days It has been a pleasureful experience and I have no complaints.
### Feishin _desktop_
Feishin is a rewrite of sonixd, a client for subsonic.
It's a really clean music client for jellyfin, I found it in nixpkgs and I use it daily.
It has many features and a modern spotify-like UI.
Sadly it's missing a download feature, meaning I cannot download music then listen to it on the road or something like that. Streaming flacs is really inefficient if you are using mobile data or some public data. I travel a lot meaning this is kind of a deal breaker, but I can just use my phone.
Here is a video of how it looks like in it's _fullscreen_ mode:
<video src="./feishin.mp4" width="100%" height="100%" controls></video>
![](fieshin_front_page.png)
### Finamp _mobile_
Finamp is an open-source jellyfin music client for Android.
It's one of the most feature rich clients out there, supporting many features also found in the mobile Spotify client.
I don't really like it's design as It doesn't really look like Spotify but that probably due to their focus not being on that. Regardless Its clean.
| Song focus | List of songs |
| :------------------: | :-------------------: |
| ![](finamp_song.png) | ![](finamp_songs.png) |
## Self-hosting
### Jellyfin
Nixpkgs has jellyfin options so we can deploy it that way. It's really straight-forward and seamless.
This example also includes a nginx configuration, since I'm assuming you want to access it from remote locations and maybe share it with friends.
```nix
{ pkgs, config, ... }: {
services.jellyfin = {
enable = true;
# Setting the home directory
# might need to create with mkdir /home/jellyfin
dataDir = "/home/jellyfin";
};
services.nginx = {
virtualHosts = {
"jelly.${config.networking.domain}" = {
forceSSL = true;
enableACME = true;
locations."/" = {
extraConfig = ''
proxy_pass http://localhost: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;
'';
};
# Enable socket for features like syncPlay and live view in the admin panel
locations."/socket" = {
extraConfig = ''
proxy_pass http://localhost: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;
'';
};
};
};
};
}
```
After this you can head to `jelly.yourdomain.com` and run the setup.
Keep in mind this is a really basic setup, all data will be stored at `/home/jellyfin` including the SQLite database.
### slskd
slskd is a fully featured modern client-server client for soulseek. You can log in to it's panel and download files from the network.
I had some problems with permissions when I was trying to use the native version from _nixpkgs_, so instead I just made an oci-container that uses linux namespaces to run applications. Docker and podman is also based on it.
**Create directories**
```bash
mkdir /home/jellyfin/Music
mkdir /home/jellyfin/Music/unsorted
```
```nix
{ pkgs, config, ... }: {
# Define the slskd container
virtualisation.oci-containers.containers = {
slskd = {
image = "slskd/slskd";
ports = [
"5030:5030" # panel
"50300:50300" # soulseek
];
volumes = [
# you can use picard or similar applications to sort them, that's why I link it to unsorted
"/home/jellyfin/Music/unsorted:/downloads"
"/home/jellyfin/Music:/music"
];
environment = {
SLSKD_SHARED_DIR = "/music";
SLSKD_DOWNLOADS_DIR = "/downloads";
SLSKD_USERNAME = "slskd username";
SLSKD_PASSWORD = "slskd password";
SLSKD_SLSK_USERNAME = "soulseek login name";
SLSKD_SLSK_PASSWORD = "soulseek login name";
SLSKD_SLSK_LISTEN_IP_ADDRESS = "0.0.0.0";
};
};
};
# Open the ports for slskd so users can download from you
networking.firewall = {
enable = true;
allowedTCPPorts = [
50300
];
allowedUDPPorts = [
50300
];
};
services.nginx = {
virtualHosts = {
"soulseek.${config.networking.domain}" = {
forceSSL = true;
enableACME = true;
locations."/" = {
extraConfig = ''
proxy_pass http://localhost:5030;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
proxy_request_buffering off;
'';
};
};
};
};
}
```
Don't forget to open up the ports on your router so that users can download from you!
## Usage
### Create a music library for jellyfin
Head to the defined jellyfin domain, and log in with the credentials you have given.
On the top right click on the profile icon and head to `Dashboard` -> `Libraries` -> `Add Media Library` and add a new music library like in the picture.
![](jellyfin_music_library.png)
### Download music
Head to the domain soulseek domain you have defined, and log into `slskd`.
Slskd is really easy to use, upon entering you are greeted with the search bar, type in anything and hit enter. Slskd will search other peers on the network for the string and return files.
![](slskd_search.png)
![](slskd_search_result.png)
After hitting download slskd will put it in `/home/jellyfin/Music/unsorted`.
Jellyfin will automatically scan you library every 3 hours bot you can override this by clicking `Scan All Libraries` in the `Dashboard`
### Connect a client.
Download a client, I recommend the ones I mentioned and connect to your server.
They will ask for a server url, which is always `https://jelly.yourdomain.com` and your user credentials.
### Enjoy
<video src="./Replay_2024-07-15_20-43-44.mp4" width="100%" height="100%" controls></video>

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

View file

@ -1,5 +1,5 @@
--- ---
title: Avoid GitHub, selfhost a frogejo instance now title: Avoid GitHub, selfhost a forgejo instance now
description: GitHub has long been the de facto place for hosting code, but as forgejo is getting federation support its a better idea to just host your own GitHub description: GitHub has long been the de facto place for hosting code, but as forgejo is getting federation support its a better idea to just host your own GitHub
date: 2024-04-25 00:00:00+0000 date: 2024-04-25 00:00:00+0000
image: yancy-min-842ofHC6MaI-unsplash.jpg image: yancy-min-842ofHC6MaI-unsplash.jpg
@ -122,7 +122,7 @@ Forgejo has runners that you can use with workflows to build software on every p
services.gitea-actions-runner.instances = { services.gitea-actions-runner.instances = {
root = { root = {
enable = true; enable = true;
url = "https://git.${config.networking.domain}"; url = "127.0.0.1:${toString services.forgejo.settings.server.HTTP_PORT}";
token = "place your token here"; token = "place your token here";
settings = { settings = {
container = { container = {

View file

@ -1,20 +1,62 @@
## Adatvédelem ## Adatvédelem
> This Regulation does not apply to the processing of personal data by a natural person in the course of a purely personal or household activity and thus with no connection to a professional or commercial activity. Personal or household activities could include correspondence and the holding of addresses, or social networking and online activity undertaken within the context of such activities. However, this Regulation applies to controllers or processors which provide the means for processing personal data for such personal or household activities ## Milyen adatokat gyűjtök?
Mivel ez egy személyes weboldal nem vagyok kötelezve arra hogy írjak az adatkezelésről. Majdnem minden paramétert az Nginx szerverem loggol, itt láthatod hogy én mit látok amikor valamelyik szolgáltatásomra felmész:
A szolgáltatásaim sem köteleznek arra hogy személyes adatot adj meg.
De a biztonság kedvéért ezt idézem: ```json
{
"msec": "1717282535.756",
"connection": "16014",
"connection_requests": "633",
"pid": "612008",
"request_id": "cfe2d77a7db2e5ca3bea0716d8c54769",
"request_length": "112",
"remote_addr": "192.168.1.1",
"remote_user": "",
"remote_port": "53236",
"time_local": "02/Jun/2024:00:55:35 +0200",
"time_iso8601": "2024-06-02T00:55:35+02:00",
"request": "OPTIONS /_matrix/client/v3/sync?filter=0&timeout=30000&set_presence=online&since=s31158_1541328_15670_64635_15313_26_839_110647_0_25 HTTP/2.0",
"request_uri": "/_matrix/client/v3/sync?filter=0&timeout=30000&set_presence=online&since=s31158_1541328_15670_64635_15313_26_839_110647_0_25",
"args": "filter=0&timeout=30000&set_presence=online&since=s31158_1541328_15670_64635_15313_26_839_110647_0_25",
"status": "204",
"body_bytes_sent": "0",
"bytes_sent": "221",
"http_referer": "",
"http_user_agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Element/1.11.66 Chrome/122.0.6261.156 Electron/29.4.0 Safari/537.36",
"http_x_forwarded_for": "",
"http_host": "4o1x5.dev",
"server_name": "4o1x5.dev",
"request_time": "0.002",
"upstream": "pink:8008",
"upstream_connect_time": "0.000",
"upstream_header_time": "0.002",
"upstream_response_time": "0.002",
"upstream_response_length": "0",
"upstream_cache_status": "",
"ssl_protocol": "TLSv1.3",
"ssl_cipher": "TLS_AES_128_GCM_SHA256",
"scheme": "https",
"request_method": "OPTIONS",
"server_protocol": "HTTP/2.0",
"pipe": ".",
"gzip_ratio": "",
"http_cf_ray": "",
"geoip_country_code": "US"
}
```
## Milyen adatot gyűjtök ## Hogyan használom fel ezt az adatot?
A szolgáltatásaim lehet hogy loggolnak IP címeket, user agenteket, url paramétereket és irányokat. Ezeket lehet hogy vagy a `docker` vagy a `systemd` felkap. Időnként beleolvasok a grafana panelem segítségével.
**De! Ezeket az adatokat soha nem osztom meg senkivel és nem is dolgozom fel másképpen!**
![Grafana panel](./dashboard.png)
## Hogyan használom ezeket az adatokat? ## Hogyan tárolom az adatokat?
Sehogyan. Semmilyen alakalommal nem használom fel, adom el vagy olvasok bele. Ezek az adatok `.log` fájlonként vannak a szerveremen.
## Hogyan tárolom ezeket az adatokat? ## Milyen sokáig tárolom az adatokat?
Az adatok ideiglenes memóriában tárolódhatnak, mint példáúl RAM, de megeshet hogy a merevlemezeimen. Maximum egy év.

View file

@ -1,23 +1,68 @@
## Privacy policy ## Privacy policy
> This Regulation does not apply to the processing of personal data by a natural person in the course of a purely personal or household activity and thus with no connection to a professional or commercial activity. Personal or household activities could include correspondence and the holding of addresses, or social networking and online activity undertaken within the context of such activities. However, this Regulation applies to controllers or processors which provide the means for processing personal data for such personal or household activities
Since this is a personal website and is not owned by a company or other entity, I don't have to disclose a privacy policy.
And since none of my services require you to enter any personal data, I won't be processing any personal information.
However, for the sake of completeness, I will include the following:
## What data I collect ## What data I collect
My services may log IP addresses, user agents, routes, query parameters. These may be logged by `docker` or `systemd`. These may be logged by `docker` or `systemd`.
I also heavily log any requests sent to my server **but purely for analytic purposes**.
Here is an example of what I will see once you visit any of my services.
```json
{
"msec": "1717282535.756",
"connection": "16014",
"connection_requests": "633",
"pid": "612008",
"request_id": "cfe2d77a7db2e5ca3bea0716d8c54769",
"request_length": "112",
"remote_addr": "192.168.1.1",
"remote_user": "",
"remote_port": "53236",
"time_local": "02/Jun/2024:00:55:35 +0200",
"time_iso8601": "2024-06-02T00:55:35+02:00",
"request": "OPTIONS /_matrix/client/v3/sync?filter=0&timeout=30000&set_presence=online&since=s31158_1541328_15670_64635_15313_26_839_110647_0_25 HTTP/2.0",
"request_uri": "/_matrix/client/v3/sync?filter=0&timeout=30000&set_presence=online&since=s31158_1541328_15670_64635_15313_26_839_110647_0_25",
"args": "filter=0&timeout=30000&set_presence=online&since=s31158_1541328_15670_64635_15313_26_839_110647_0_25",
"status": "204",
"body_bytes_sent": "0",
"bytes_sent": "221",
"http_referer": "",
"http_user_agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Element/1.11.66 Chrome/122.0.6261.156 Electron/29.4.0 Safari/537.36",
"http_x_forwarded_for": "",
"http_host": "4o1x5.dev",
"server_name": "4o1x5.dev",
"request_time": "0.002",
"upstream": "pink:8008",
"upstream_connect_time": "0.000",
"upstream_header_time": "0.002",
"upstream_response_time": "0.002",
"upstream_response_length": "0",
"upstream_cache_status": "",
"ssl_protocol": "TLSv1.3",
"ssl_cipher": "TLS_AES_128_GCM_SHA256",
"scheme": "https",
"request_method": "OPTIONS",
"server_protocol": "HTTP/2.0",
"pipe": ".",
"gzip_ratio": "",
"http_cf_ray": "",
"geoip_country_code": "US"
}
```
## How will I use or process your data? ## How will I use or process your data?
I won't. I never publish, read, save or sell the data. I look thru it via my grafana panel.
**But I never share, sell or process the information otherwise**
![Grafana panel](./dashboard.png)
## How do I store your data? ## How do I store your data?
This data may be stored only in volatile storage such as RAM or my hard drives. This data may be stored only in volatile storage such as RAM or my hard drives.
Nginx logs are stored in a `.log` format, pure text.
But promtail also processes these logs and sends them to loki for `in-memory` storage.
## How long do I store data ## How long do I store data
I store them for a day mostly, as I have script to delete them. I store them for a year at most, as they tend to clog up my storage.

1
docker-compose.yml Normal file
View file

@ -0,0 +1 @@
version: "3"

View file

@ -2,16 +2,16 @@
"nodes": { "nodes": {
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1713344939, "lastModified": 1720954236,
"narHash": "sha256-jpHkAt0sG2/J7ueKnG7VvLLkBYUMQbXQ2L8OBpVG53s=", "narHash": "sha256-1mEKHp4m9brvfQ0rjCca8P1WHpymK3TOr3v34ydv9bs=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "e402c3eb6d88384ca6c52ef1c53e61bdc9b84ddd", "rev": "53e81e790209e41f0c1efa9ff26ff2fd7ab35e27",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "NixOS", "owner": "NixOS",
"ref": "nixos-23.11", "ref": "nixos-24.05",
"repo": "nixpkgs", "repo": "nixpkgs",
"type": "github" "type": "github"
} }

View file

@ -1,7 +1,7 @@
{ {
description = "Developer shell"; description = "Developer shell";
inputs = { inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11"; nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.05";
}; };
outputs = { self, nixpkgs, ... }: outputs = { self, nixpkgs, ... }:
let let

View file

@ -0,0 +1,13 @@
{{ define "body-class" }}template-search{{ end }}
{{ define "head" }}
{{- with .OutputFormats.Get "json" -}}
<link rel="preload" href="{{ .RelPermalink }}" as="fetch" crossorigin="anonymous">
{{- end -}}
{{ end }}
{{ define "main" }}
<h1>Projects</h1>
{{ partialCached "footer/footer" . }}
{{ end }}

View file

@ -0,0 +1,20 @@
{{- $ThemeVersion := "3.25.0" -}}
<footer class="site-footer">
<section class="copyright">
&copy;
{{ if and (.Site.Params.footer.since) (ne .Site.Params.footer.since (int (now.Format "2006"))) }}
{{ .Site.Params.footer.since }} -
{{ end }}
{{ now.Format "2006" }} {{ default .Site.Title .Site.Copyright }}
</section>
<section class="powerby">
{{- $Generator := `<a href="https://gohugo.io/" target="_blank" rel="noopener">Hugo</a>` -}}
{{- $Theme := printf `<b><a href="https://github.com/CaiJimmy/hugo-theme-stack" target="_blank" rel="noopener" data-version="%s">Stack</a></b>` $ThemeVersion -}}
{{- $DesignedBy := `<a href="https://jimmycai.com" target="_blank" rel="noopener">Jimmy</a>` -}}
{{ T "footer.builtWith" (dict "Generator" $Generator) | safeHTML }} <br />
{{ T "footer.designedBy" (dict "Theme" $Theme "DesignedBy" $DesignedBy) | safeHTML }}
</section>
</footer>

BIN
static/dashboard.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 764 KiB