26 Commits

Author SHA1 Message Date
yehor
0b10a38921 Update version
All checks were successful
Build release image / build (push) Successful in 1m18s
2025-10-08 11:45:44 +03:00
yehor
6e8c00c313 Update heading styles. self-hosted list WIP 2025-10-08 11:45:28 +03:00
yehor
cf8e3ac9ae Add self-hosted list
All checks were successful
Build release image / build (push) Successful in 1m24s
2025-10-07 23:36:01 +03:00
yehor
727906d461 Update theme
All checks were successful
Build release image / build (push) Successful in 1m17s
2025-10-07 22:58:30 +03:00
yehor
756312021a Add discussion link
All checks were successful
Build release image / build (push) Successful in 1m26s
2025-10-07 21:05:49 +03:00
yehor
d6d3cd6d00 Fix blog table of contents styles 2025-10-07 20:21:25 +03:00
yehor
6d43975f0b Fix typo 2025-10-07 14:53:26 +03:00
yehor
013a41bb02 Update version
All checks were successful
Build release image / build (push) Successful in 1m19s
2025-10-07 13:11:05 +03:00
yehor
3daee8bc4d Add footer contact links 2025-10-07 13:04:05 +03:00
yehor
342c025697 Fix headers 2025-10-07 12:56:39 +03:00
yehor
a603f5160a Add new post 2025-10-07 12:54:19 +03:00
yehor
846f09f817 Add Pixelfed link
All checks were successful
Build release image / build (push) Successful in 2m14s
2025-10-06 15:23:38 +03:00
yehor
d930d6774d Add matrix link
All checks were successful
Build release image / build (push) Successful in 2m30s
2025-08-31 23:58:04 +03:00
yehor
513af6bfa7 Add Pixelfed. Remove Matrix
Some checks failed
Build release image / build (push) Has been cancelled
2025-08-08 11:41:25 +03:00
yehor
c74faccd78 Update version
All checks were successful
Build release image / build (push) Successful in 3m15s
2025-07-20 20:09:31 +03:00
yehor
95ce34b12b Fix column width on the home page 2025-07-20 20:09:13 +03:00
yehor
ff4c256544 Fix broken links
All checks were successful
Build release image / build (push) Successful in 3m50s
2025-07-20 13:17:14 +03:00
yehor
e6633ce255 Remove docs. Make it better
Some checks failed
Build release image / build (push) Failing after 1m29s
2025-07-20 13:06:18 +03:00
yehor
497239cc76 Add more on network
All checks were successful
Build release image / build (push) Successful in 1m33s
2025-06-11 16:45:01 +03:00
yehor
4c7a1a6721 Fix docs structure
All checks were successful
Build release image / build (push) Successful in 1m55s
2025-06-11 16:07:33 +03:00
yehor
339b714cbd Fix CI job step name 2025-05-22 09:04:53 +03:00
yehor
359d62df58 Add network documentation
All checks were successful
Build release image / build (push) Successful in 1m40s
2025-05-21 18:30:06 +03:00
yehor
466d510264 Add homelab overview
All checks were successful
Build release image / build (push) Successful in 1m15s
2025-05-21 12:20:19 +03:00
yehor
a0a98c0014 Fix footer feed links
All checks were successful
Build release image / build (push) Successful in 1m32s
2025-05-21 11:52:36 +03:00
yehor
f9be7b0c10 Add new blog post
Some checks failed
Build release image / build (push) Failing after 1m3s
2025-05-21 11:43:49 +03:00
yehor
861bdcd686 Add deleted-post page
All checks were successful
Build release image / build (push) Successful in 1m28s
2025-05-21 10:41:18 +03:00
46 changed files with 1613 additions and 110 deletions

View File

@@ -32,7 +32,7 @@ jobs:
password: ${{ secrets.IMAGE_REGISTRY_PASSWORD }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build docker image
- name: Build Docker image
uses: docker/build-push-action@v6
with:
context: .

View File

@@ -116,4 +116,6 @@ binary_sensor:
pin:
number: D5
mode: INPUT
```
```
<BlogDiscussions/>

View File

@@ -49,4 +49,6 @@ Now we need to create a handler of the Aqara button in `automations.yaml`:
- data:
message: "Someone near your front door"
service: notify.push
```
```
<BlogDiscussions/>

View File

@@ -134,4 +134,6 @@ Now we can rely on that group’s state to check if there is nobody home. I’ve
service: notify.push
```
That is all for now. Thanks for reading.
That is all for now. Thanks for reading.
<BlogDiscussions/>

View File

@@ -208,4 +208,6 @@ Also, this automation should be able to run in parallel to make it possible to h
```yaml
mode: parallel
max: 10
```
```
<BlogDiscussions/>

View File

@@ -40,4 +40,6 @@ binary_sensor:
friendly_name: "Bed occupancy"
device_class: occupancy
value_template: "{{is_state('binary_sensor.bed_occupancy_door_side', 'off') or is_state('binary_sensor.bed_occupancy_window_side', 'off')}}"
```
```
<BlogDiscussions/>

View File

@@ -42,4 +42,6 @@ action:
![Parsing action](parse_action.png)
Here we are checking for the `engine is off` text in incoming SMS to perform some action. For example, to set the value of some `input_boolean`.
Here we are checking for the `engine is off` text in incoming SMS to perform some action. For example, to set the value of some `input_boolean`.
<BlogDiscussions/>

View File

@@ -105,3 +105,5 @@ switch:
```
That’s it for today. Thanks for reading.
<BlogDiscussions/>

View File

@@ -237,4 +237,6 @@ Before placing our power supply inside the TV we need to make sure it is isolate
So the overall picture is looking like this:
![](overview.png)
![](overview.png)
<BlogDiscussions/>

View File

@@ -85,4 +85,6 @@ Compile, flash, open logs and start firing into our device with your IR remote.
[17:34:51][D][remote.samsung:055]: Received Samsung: data=0xE0E020DF
```
You can now use this data with the ESPHome [Remote Transmitter](https://esphome.io/components/remote_transmitter.html) component to build, for example, something like [this](/2021-01-13-building-wifi-ir-remote-control-for-any-tv-with-esp8266-wemos-d1-mini-and-esphome/index.md).
You can now use this data with the ESPHome [Remote Transmitter](https://esphome.io/components/remote_transmitter.html) component to build, for example, something like [this](/2021-01-13-building-wifi-ir-remote-control-for-any-tv-with-esp8266-wemos-d1-mini-and-esphome/index.md).
<BlogDiscussions/>

View File

@@ -120,4 +120,6 @@ Decreasing the volume action is the same, but with negative `target`:
service: esphome.amplifier_set_volume
data:
target: -50
```
```
<BlogDiscussions/>

View File

@@ -8,7 +8,7 @@ Do you want to know how and where RandomPlace is hosted? Or do you just want to
:::info
This post is from the past. From far away times when this website had another domain, another name and another hosting place. For current setup, please see [HomeLab](/docs/homelab).
This post is from the past. From far away times when this website had another domain, another name and another hosting place.
Still, this guide can be useful.
@@ -119,4 +119,6 @@ You'll get an email notification on the address added here when there will be ti
After certificate generation, we should open Settings on the same Certificates tab, find our domain service, and choose the newly generated certificate for it.
That's it!
That's it!
<BlogDiscussions/>

View File

@@ -43,4 +43,6 @@ In your Home Assistant go to _Settings -> Devices & services_ and click the _"Ad
In the configuration window that appeared you need to set your NAS's local IP address as a _Host_ and leave the _Port_ number unchanged.
Hit _Submit_ and you are done.
Hit _Submit_ and you are done.
<BlogDiscussions/>

View File

@@ -54,4 +54,6 @@ The authorization header should have the next format: `PVEAPIToken=<proxmox user
You can use `shutdown` or `reboot` as a `command`.
After restarting Home Assistant you will have a new service available. In our example, it would be `rest_command.spacedock_one_shutdown`. Calling it will do the trick.
After restarting Home Assistant you will have a new service available. In our example, it would be `rest_command.spacedock_one_shutdown`. Calling it will do the trick.
<BlogDiscussions/>

View File

@@ -105,4 +105,6 @@ And up it back with a system service, also enabling it:
sudo systemctl start wg-quick@wg0 && sudo systemctl enable wg-quick@wg0
```
Further interface control should be performed through `systemctl` as well like `systemctrl stop`, `systemctl restart` or `systemctl status`.
Further interface control should be performed through `systemctl` as well like `systemctrl stop`, `systemctl restart` or `systemctl status`.
<BlogDiscussions/>

View File

@@ -0,0 +1,103 @@
---
slug: make-one-proxmox-node-to-wol-another
title: "Make one Proxmox node to wake-on-lan another"
tags: [self-hosting, homelab, Proxmox, WOL]
image: /img/homelab.png
---
Nothing is eternal, especially the relevance of documentation. I think help.ubuntu.com is an absolute winner, holding the largest number of outdated and irrelevant pages. But that's not a topic for today's post.
One of my Proxmox cluster nodes can't power itself on after the outage. But it supports wake-on-LAN, so I decided that another node could power it on. And the simplicity of this task was overrated by me.
<!-- truncate -->
:::warning
Wake on LAN doesn't work across VLANs. Magic packets could be sent and received only inside a single subnet.
:::
## The victim
First of all, even after enabling "Wake up on PCI event" or something in BIOS it was not working because WoL was still disabled on a software level. It can be checked with:
```bash
ethtool enp1s0
```
Where `enp1s0` is a physical network interface of a Proxmox node, not a bridge.
There should be `Wake-on:` setting among others. In my case it was `Wake-on: d`, which means that wake-on-LAN is disabled, according to `ethtool` documentation:
```
p Wake on phy activity
u Wake on unicast messages
m Wake on multicast messages
b Wake on broadcast messages
a Wake on ARP
g Wake on MagicPacket(tm)
s Enable SecureOn(tm) password for MagicPacket(tm)
d Disable (wake on nothing). This option clears all previous
options.
```
We need to set it to wake by the MagicPacket(tm). We need to create a config file for this to be enabled on system start. But first we need to:
```bash
ip link show enp1s0
```
and write down our network device MAC address. Then create a file:
```bash
nano /etc/systemd/network/90-wakeonlan.link
```
with the next content:
```
[Match]
MACAddress=<mac-address-here>
[Link]
NamePolicy=kernel database onboard slot path
MACAddressPolicy=persistent
WakeOnLan=magic
```
After that we need to reboot and check WOL status again:
```bash
ethtool enp1s0
```
Now `Wake-on` should be set to `g`.
## The one who bothering
On another node we need to install an util that will be sending a magic packet:
```bash
apt update
apt install etherwake
```
Now we can power the victim off and try to wake it with:
```bash
etherwake -i vmbr0 <mac_address>
```
Where `vmbr0` is a bridge network interface of current Proxmox node, and `<mac_address>` is a MAC address of the victim's physical network interface.
If it works, we can now add a cron job to wake our victim upon current node startup, adding some delay to make sure the network is ready:
```bash
crontab -e
```
Cron job line to add:
```
@reboot sleep 30s && /usr/sbin/etherwake -i vmbr0 <mac_address>
```
<BlogDiscussions/>

View File

@@ -0,0 +1,187 @@
---
slug: proxmox-ve-on-hetzner-dedicated-server
title: "Proxmox VE and PBS on Hetzner dedicated server"
tags: [self-hosting, homelab, Proxmox, Proxmox VE, PBS, Hetzner, Tailscale, Caddy]
image: /img/homelab.png
---
Circumstances forced me to move all my self-hosted services to a location that does not depend on my living place. Someday, I hope I'll have all that hosted at home again, but now I want to describe my path of setting up a Proxmox VE on a Hetzner dedicated server together with Proxmox Backup Server and Tailscale with backups on Backblaze. This could look like a trivial task at first, but I faced some issues and obstacles I want to document here, for me to remember and for others to be informed.
I want to warn that this is not a full step-by-step guide. It is rather notes on the process and steps I followed.
<!-- truncate -->
## Installation
There is documentation on the installation process at [Hetzner](https://community.hetzner.com/tutorials/install-and-configure-proxmox_ve). There are options, and I chose the first one - installing Proxmox VE on Debian.
So, according to the docs, I booted a [Rescue System](https://docs.hetzner.com/robot/dedicated-server/troubleshooting/hetzner-rescue-system/) and installed Debian with the [installimage](https://docs.hetzner.com/robot/dedicated-server/operating-systems/installimage/).
Then I followed the [guide from Proxmox Wiki](https://pve.proxmox.com/wiki/Install_Proxmox_VE_on_Debian_13_Trixie) to install Proxmox VE. There is a step where you first install a new kernel and reboot to activate it. I was forced to reboot the server twice to make it appear online again. Have no idea why.
## Network
Now to the hard part.
The initial plan was to have all LXCs in a single local network to allow internal communication. Also, the host and some containers should have public IPs for external access.
I reviewed a lot of network configuration options around the internet and chose a bridged setup with masquerading (NAT).
For the network I edited `/etc/network/interfaces` like this:
```
auto lo
iface lo inet loopback
iface lo inet6 loopback
iface enp5s0 inet manual
iface enp5s0 inet6 manual
auto vmbr0
iface vmbr0 inet static
address <Public IPv4>/26
gateway <Public IPv4 gateway>
pointopoint <Public IPv4 gateway>
bridge-ports enp5s0
bridge-stp off
bridge-fd 0
up route add -net <Public IPv4 gateway - 1> netmask 255.255.255.192 gw <Public IPv4 gateway> dev vmbr0
post-up echo 1 > /proc/sys/net/ipv4/ip_forward
post-up echo 1 > /proc/sys/net/ipv6/conf/all/forwarding
post-up iptables -t nat -A PREROUTING -i vmbr0 -p tcp -d <Public IPv4> --dport 21074 -j DNAT --to 192.168.50.3
post-down iptables -t nat -D PREROUTING -i vmbr0 -p tcp -d <Public IPv4> --dport 21074 -j DNAT --to 192.168.50.3
iface vmbr0 inet6 static
address <Public IPv6>/64
gateway <Public IPv6 gateway>
auto vmbr1
iface vmbr1 inet static
address 192.168.50.1/24
netmask 255.255.255.0
bridge-ports none
bridge-stp off
bridge-fd 0
post-up iptables -t raw -I PREROUTING -i fwbr+ -j CT --zone 1
post-down iptables -t raw -D PREROUTING -i fwbr+ -j CT --zone 1
post-up iptables -t nat -A POSTROUTING -s '192.168.50.0/24' -o vmbr0 -j MASQUERADE
post-down iptables -t nat -D POSTROUTING -s '192.168.50.0/24' -o vmbr0 -j MASQUERADE
```
Let's see what's going on in here.
For the containers that don't require a public IP, I choose `vbmr1` bridge, set some IP from the local IP range (192.168.50.x), and use host local IP as a gateway:
![LXC local network](vmbr1.png)
For LXCs that require a separate public IP, I choose the `vmbr0` bridge, set the IP, gateway, and MAC address provided by Hetzner.
![LXC public network](vmbr0.png)
The route with the `<Public IPv4 gateway - 1>` is a route from the official [Hetzner docs](https://community.hetzner.com/tutorials/install-and-configure-proxmox_ve). That doc was updated while I was writing this post, and the line was removed from the example network configuration there. Some network configuration guides across the internet still have it, so I'm leaving it as is for now. If your public IP gateway is, for example, 67.11.34.23, the route will be
```
up route add -net 67.11.34.22 netmask 255.255.255.192 gw 67.11.34.23 dev vmbr0
```
The next lines enable IP forwarding across networks:
```
post-up echo 1 > /proc/sys/net/ipv4/ip_forward
post-up echo 1 > /proc/sys/net/ipv6/conf/all/forwarding
```
And here is an example of forwarding a port `21074` from the public IP to the local IP of a single LXC:
```
post-up iptables -t nat -A PREROUTING -i vmbr0 -p tcp -d <Public IPv4> --dport 21074 -j DNAT --to 192.168.50.3
post-down iptables -t nat -D PREROUTING -i vmbr0 -p tcp -d <Public IPv4> --dport 21074 -j DNAT --to 192.168.50.3
```
For the local network `vmbr1` the next lines are needed to make Proxmox Firewall work properly:
```
post-up iptables -t raw -I PREROUTING -i fwbr+ -j CT --zone 1
post-down iptables -t raw -D PREROUTING -i fwbr+ -j CT --zone 1
```
### Network security
Ports `8006`, `22`, and `8007` are opened on the Proxmox host in the Proxmox firewall, but explicitly closed in the Hetzner firewall. That way, I can use Proxmox VE and PBS web UI only from the Tailscale network, but, in case of an emergency or misconfiguration, I can open critical ports in Hetzner firewall to get access using server's public IP.
## Public Reverse Proxy
I know it is not the best practice to install anything directly on a Proxmox host, but this looks like a perfect decision, as it already has a public IP address, and I can't unassign it because this is the only way to access the server in case of failure.
So I decided to install Caddy directly to a Proxmox Host and open ports `80` and `443` to it. Caddy handles requests and then proxies them to the local IPs of LXCs:
```
git.nicelycomposed.codes {
reverse_proxy 192.168.50.3:3000
}
```
## Tailscale and Internal Reverse Proxy
They call it "bastion host". A single point of connecting to your internal resources that you don't want to expose publicly. I have an LXC for this with Tailscale and another instance of Caddy installed. Let's see how it works on an example.
I want to securely connect to the Proxmox VE web UI using a valid SSL certificate at `https://pve.int.example.com`.
First, to make Tailscale work inside an LXC, additional configuration should be made on the Proxmox host. LXC configuration file can be found at `/etc/pve/lxc/<CT_ID>.conf`. Those two lines should be added to the file:
```
lxc.cgroup2.devices.allow: c 10:200 rwm
lxc.mount.entry: /dev/net/tun dev/net/tun none bind,create=file
```
Then just restart the LXC.
Then, I installed Tailscale and Caddy on my "bastion host". Then I created a DNS record to point `pve.int.example.com` to an IP address of my bastion host in the Tailscale network:
```
A pve.int.example.com 10.11.12.13
```
Then, in the Caddy config, I proxied `pve.int.example.com` to the local IP of my Proxmox host and port `8006`, using HTTPS and skipping TLS verification because of Proxmox's default self-signed certificate:
```
pve.int.example.com {
reverse_proxy 192.168.50.1:8006 {
transport http {
tls
tls_insecure_skip_verify
}
}
}
```
Now I'm able to point my browser to `https://pve.int.example.com` while connected to my Tailscale network.
:::warning
As all ports are closed on the "bastion host" and it is not exposed publicly, the default ACME HTTP challenge will not work for Caddy to issue SSL certificates for internal resources. [DNS challenge](https://caddyserver.com/docs/json/admin/identity/issuers/acme/challenges/) should be used instead.
:::
I can add other internal resources hosted on other LXCs in the same way:
```
dockge.int.example.com {
reverse_proxy 192.168.50.4:5000
}
element-admin.int.example.com {
reverse_proxy 192.168.50.8:8080
}
```
## Proxmox Backup Server
It was the simplest part. I know this is not the most recommended method, but my Proxmox Backup Server is [installed on the Proxmox VE host](https://pbs.proxmox.com/docs/installation.html#install-proxmox-backup-server-on-proxmox-ve).
After installing it and configuring it to use [Backblaze S3 storage](https://pbs.proxmox.com/docs/storage.html#datastores-with-s3-backend), I just added it as a storage to Proxmox VE using the local IP of the host.
![PBS config](pbs.png)
## Conclusion
Have no idea why everyone wants to write a conclusion for each post nowadays. It looks like a forced conclusion to a school physics problem in most cases: "Solving this problem of moving trains, we found out that trains can move".
Have a nice tinkering.
<BlogDiscussions/>

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

View File

@@ -1,9 +0,0 @@
---
sidebar_position: 1
---
# What is it?
This is my project of publicly available documentation of my home servers and services.
Working on it...

1
docs/index.md Normal file
View File

@@ -0,0 +1 @@
Hello World!

View File

@@ -36,6 +36,12 @@ const config = {
locales: ['en'],
},
markdown: {
mermaid: true,
},
themes: ['@docusaurus/theme-mermaid'],
scripts: [
{
src: 'https://plausible.nicelycomposed.codes/js/script.outbound-links.js',
@@ -56,6 +62,9 @@ const config = {
showReadingTime: true,
feedOptions: {
type: ['rss', 'atom'],
title: "Yehor Vialov's Blog",
description: 'Some notes, interesting things and projects',
copyright: 'Copyright © ${new Date().getFullYear()} Yehor Vialov',
xslt: true,
},
blogSidebarTitle: 'Timeline',
@@ -89,64 +98,41 @@ const config = {
srcDark: 'img/logo_dark.svg',
},
items: [
{
type: 'docSidebar',
sidebarId: 'homelabSidebar',
position: 'left',
label: 'HomeLab',
},
{ to: '/blog', label: 'Blog', position: 'left' },
{ to: '/selfhosted-list', label: 'Self-hosted List', position: 'left' },
],
},
footer: {
style: 'dark',
style: 'light',
links: [
{
title: 'This site sections',
title: 'This site sections:',
items: [
{
label: 'Homelab',
to: '/docs/homelab',
},
{
label: 'Blog',
to: '/blog',
},
],
},
{
title: 'My',
items: [
{
label: 'Code',
href: 'https://git.nicelycomposed.codes/yehor',
label: 'Blog RSS feed',
to: 'pathname:///blog/rss.xml',
},
{
label: 'Blog Atom feed',
to: 'pathname:///blog/atom.xml',
},
],
},
{
title: 'Me on',
title: 'Feel free to contact me with questions and/or criticisms:',
items: [
{
label: 'Matrix',
to: 'https://matrix.to/#/@yehor:vi.place',
},
{
label: 'Mastodon',
href: 'https://techhub.social/@estevez',
to: 'https://techhub.social/@estevez',
},
{
label: 'Pixelfed',
href: 'https://pixelfed.social/estevez',
},
{
label: 'GitHub',
href: 'https://github.com/estevez-dev',
},
{
label: 'Untappd',
href: 'https://untappd.com/user/estevezz',
},
{
label: 'LinkedIn',
href: 'https://www.linkedin.com/in/yehor-vialov-2a362158/',
},
],
},

View File

@@ -1,6 +1,6 @@
{
"name": "yevi-org",
"version": "0.1.0",
"version": "0.4.1",
"private": true,
"scripts": {
"docusaurus": "docusaurus",
@@ -16,6 +16,7 @@
"dependencies": {
"@docusaurus/core": "3.7.0",
"@docusaurus/preset-classic": "3.7.0",
"@docusaurus/theme-mermaid": "^3.7.0",
"@mdx-js/react": "^3.0.0",
"clsx": "^2.0.0",
"prism-react-renderer": "^2.3.0",

View File

@@ -16,10 +16,9 @@
*/
const sidebars = {
homelabSidebar: [{
type: 'doc',
id: 'homelab/index',
label: 'HomeLab',
docsSidebar: [{
type: 'autogenerated',
dirName: '.',
},],

View File

@@ -0,0 +1,16 @@
import styles from './styles.module.css';
export default function BlogDiscussions() {
const Svg = require('@site/static/icons/matrix.svg').default;
return (
<section className={styles.blogDiscussions}>
<a className={styles.blogDiscussions_container} href="https://matrix.to/#/%23yevi-org-pub:vi.place" target='_blank'>
<Svg fill="currentColor" className={styles.icon} role="img" />
<span className={styles.linkText}>Join discussion at Matrix</span>
</a>
</section>
);
}

View File

@@ -0,0 +1,28 @@
.blogDiscussions {
display: flex;
flex-direction: row;
justify-content: center;
padding: 1rem 0;
}
.blogDiscussions_container {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
align-items: center;
}
.linkText {
width: 12rem;
}
.icon {
width: 2rem;
height: 2rem;
padding-right: 0.5rem;
}
.icon path {
fill: var(--ifm-heading-color) !important;
}

View File

@@ -3,36 +3,95 @@ import Heading from '@theme/Heading';
import styles from './styles.module.css';
const FeatureList = [
{
title: 'HomeLab Documented',
link: 'docs/homelab',
Svg: require('@site/static/img/homelab.svg').default,
description: (
<>
Here I'm trying my best in documenting my home servers and services.
</>
),
},
{
title: 'Blog',
link: 'blog',
Svg: require('@site/static/img/blog.svg').default,
Svg: require('@site/static/icons/blog.svg').default,
description: (
<>
Some notes, interesting things and projects.
</>
),
},
{
title: 'Git',
link: 'https://git.nicelycomposed.codes/yehor',
Svg: require('@site/static/icons/gitea.svg').default,
description: (
<>
My code
</>
),
},
{
title: 'Mastodon',
link: 'https://techhub.social/@estevez',
Svg: require('@site/static/icons/mastodon.svg').default,
description: (
<>
My micro blog at techhub.social
</>
),
},
{
title: 'Matrix',
link: 'https://matrix.to/#/@yehor:vi.place',
Svg: require('@site/static/icons/matrix.svg').default,
description: (
<>
If you want to chat (with end-to-end encryption)
</>
),
},
{
title: 'Pixelfed',
link: 'https://pixelfed.social/estevez',
Svg: require('@site/static/icons/pixelfed.svg').default,
description: (
<>
For some photography
</>
),
},
{
title: 'GitHub',
link: 'https://github.com/estevez-dev',
Svg: require('@site/static/icons/github.svg').default,
description: (
<>
Some forks and contributions
</>
),
},
{
title: 'Untappd',
link: 'https://untappd.com/user/estevezz',
Svg: require('@site/static/icons/untappd.svg').default,
description: (
<>
Budmo!
</>
),
},
{
title: 'Linkedin',
link: 'https://www.linkedin.com/in/yehor-vialov-2a362158/',
Svg: require('@site/static/icons/linkedin.svg').default,
description: (
<>
They say I need this to find any work
</>
),
},
];
function Feature({ Svg, title, link, description }) {
return (
<div className={clsx('col col--6')}>
<div className={clsx('col col--3', styles.featureBlock)}>
<div className="text--center">
<a href={link} className={styles.featureLink}>
<Svg className={styles.featureSvg} role="img" />
<a href={link} target='_blank' className={styles.featureLink}>
<Svg fill="currentColor" className={styles.featureSvg} role="img" />
</a>
</div>
<a href={link} className={styles.featureLink}>

View File

@@ -5,9 +5,33 @@
width: 100%;
}
.featureBlock {
padding-bottom: 1rem;
}
@media (max-width: 996px) {
.featureBlock {
--ifm-col-width: 50%;
}
}
@media (max-width: 500px) {
.featureBlock {
--ifm-col-width: 100%;
}
}
.featureSvg {
height: 200px;
width: 200px;
height: 60px;
width: 60px;
}
.featureSvg path {
fill: var(--ifm-link-color) !important;
}
.featureBlock:hover .featureSvg path {
opacity: 0.7;
}
.featureLink {
@@ -23,4 +47,8 @@
.featureLink:visited {
text-decoration: none;
color: unset;
}
.featureLink p {
color: var(--ifm-color-secondary-contrast-foreground);
}

View File

@@ -11,12 +11,19 @@
--ifm-color-primary-darker: #471947;
--ifm-color-primary-darkest: #3b143b;
--ifm-color-primary-light: #3b143b;
--ifm-color-primary-lighter: #612161;
--ifm-color-primary-lightest: #6d266d;
--ifm-color-primary-lighter: #712471;
--ifm-color-primary-lightest: #9d389d;
--ifm-code-font-size: 95%;
--docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.1);
--ifm-footer-link-hover-color: #b07ab0;
--ifm-link-color: var(--ifm-color-primary-lightest)
--ifm-link-color: var(--ifm-color-primary-lightest);
--ifm-global-shadow-lw: 0 1px 2px 0 #541d5428;
--ifm-heading-color: #575757;
}
.hero--primary {
--ifm-hero-background-color: transparent;
--ifm-hero-text-color: var(--ifm-font-color-base);
}
/* For readability concerns, you should choose a lighter palette in dark mode. */
@@ -30,4 +37,14 @@
--ifm-color-primary-lightest: #d1b2d1;
--docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.3);
--ifm-link-color: var(--ifm-color-primary-darker);
--ifm-heading-color: #919191;
}
h1 a,
h2 a,
h3 a,
h4 a,
h5 a,
h6 a {
color: var(--ifm-heading-color) !important;
}

15
src/pages/deleted-post.md Normal file
View File

@@ -0,0 +1,15 @@
---
title: This post was removed
description: A message about removed content
hide_table_of_contents: true
---
# You probably got here visiting a link somewhere on the internet
Sorry to say, but this post was removed because of one of the reasons (or because of all of them):
- It was critically outdated
- It was misleading
- It was stupid
- It has no historical value
You can check my [other blog posts](/blog) or start from the [home page](/).

View File

@@ -13,10 +13,10 @@ function HomepageHeader() {
<header className={clsx('hero hero--primary', styles.heroBanner)}>
<div className="container">
<Heading as="h1" className="hero__title">
{siteConfig.title}
Yehor Vialov
</Heading>
<p className="hero__subtitle">{siteConfig.tagline}</p>
<div className={styles.buttons}>
<p className="hero__subtitle">Public profiles and publications</p>
{/* <div className={styles.buttons}>
<Link
className="button button--secondary button--lg"
to="https://git.nicelycomposed.codes/yehor">
@@ -27,11 +27,6 @@ function HomepageHeader() {
to="https://techhub.social/@estevez">
Mastodon
</Link>
<Link
className="button button--secondary button--lg"
to="https://pixelfed.social/estevez">
Pixelfed
</Link>
<Link
className="button button--secondary button--lg"
to="https://github.com/estevez-dev">
@@ -47,7 +42,7 @@ function HomepageHeader() {
to="https://www.linkedin.com/in/yehor-vialov-2a362158/">
LinkedIn
</Link>
</div>
</div> */}
</div>
</header>
);

View File

@@ -1,7 +0,0 @@
---
title: Markdown page example
---
# Markdown page example
You don't need React to write simple standalone pages.

View File

@@ -0,0 +1,83 @@
---
title: Self-hosted List
description: A list of services I'm currently hosting for myself, family and friends
---
A list of services I'm currently hosting for myself, family and friends. Grouped by access levels and sorted by gut feeling.
## Publicly accessible
Services anyone on the internet can access.
### This website (Docusaurus)
[Service](https://www.yevi.org) | [Product](https://docusaurus.io)
This static site generator is mainly designed for documentation, but has a blog feature, pages, Markdown, and MDX support. When I decided to leave Ghost behind for something database-less, Markdown-ish, and stored in git, I checked different similar projects, like Hugo, for example. Docusaurus had the cleanest documentation, nicest look, and a very detailed example of a working website once you set it up. Keep it up, Docusaurus!
### Gitea
[Service](https://git.nicelycomposed.codes) | [Product](https://about.gitea.com)
When I decided to self-host a Git server, GitLab was the first option I tried, as it was familiar to me from my day job. I launched it on an old Intel NUC with only 2 GB of memory... And started to search for lighter alternatives. So here I am with a Gitea instance that hosts my old repositories from GitHub, as well as a lot of private repos with different stuff. Gitea is fast, lightweight, single-binary, and has everything I need, including GitHub-compatible CI/CD.
## Restricted
Services exposed to the internet, but require authorization.
### Plausible Analytics
[Product](https://plausible.io)
Google Analytics was my one-stop service for a long time, but it slowly enshittified into a huge, overcomplicated pile of pages and graphs you can hardly understand. Lack of fine documentation and constant requests to a user to migrate, fix, review, or reconfigure something didn't add any comfort in using it, while "Easy to use and privacy-friendly Google Analytics alternative" became more and more popular Google Search request.
[Umami](https://umami.is) was the first thing I tried. It was almost perfect service for my needs until I faced the need to use API calls to send events from my pet project app. So now I'm with Plausible, and it looks like it is here to stay.
### Plane
[Product](https://plane.so/project-management)
The only service I'm not happy with, but still using. Plane is slowly evolving into Jira. They even launched their own Confluence recently. While it is still a good project management software, I need something simpler for my needs. And there are some alternatives, but I have my pet-project tickets in Plane, and the migration will be a painful manual job. I'm not ready for this yet.
### Kan.bn
[Product](https://kan.bn)
It is a simple but very nice kanban board. I'm not sure I will replace Plane with it, but I'm using it now as a personal to-do list. And for my homelab stuff, I'll never finish.
### Outline
[Product](https://www.getoutline.com)
Need to store personal notes, family recipes, or a team’s knowledge base? Get an Outline in any of those cases and in other cases as well. The thing is so simple yet powerful and nice looking, I recommend setting it up even if you think you don't need it. As a bonus, mobile UI feels like a native app. My dream note-taking and knowledge-holding software looks and feels like Outline, has its collaboration features, but stores all notes locally like Obsidian does. For offline access at any time. Did you find something like this yet? Or maybe developing right now? No? Then I'll stick to the Outline for now.
- **Yamtrack**
- **AdventureLog**
- **Authentik**
- **Synapse** Matrix server
- **Matrix Authentication Service**
- **Home Assistant**
- **Plex**
- **n8n**
- **FreshRSS**
## Internal
Services accessible only from my home network or Tailnet.
- Zoraxy
- Caddy
- Grafana
- Prometheus
- InfuxDB
- Dockge
- Studio Code Server
- Gitea Action Runner
- Element Admin
- Sonarr
- Radarr
- Prowlarr
- qBittorrent
- Proxmox Backup Server
## Operating Systems
- TrueNAS Community Edition
- Proxmox VE
## Tools
- Tailscale

View File

@@ -0,0 +1,13 @@
import React from 'react';
// Import the original mapper
import MDXComponents from '@theme-original/MDXComponents';
//Import custom component
import BlogDiscussions from '@site/src/components/BlogDiscussions';
export default {
// Re-use the default mapping
...MDXComponents,
// Map the "<BlogDiscussions>" tag to our BlogDiscussions component
// `BlogDiscussions` will receive all props that were passed to `<BlogDiscussions>` in MDX
BlogDiscussions,
};

21
static/icons/blog.svg Normal file
View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg height="800px" width="800px" version="1.1" id="_x32_" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 512 512" xml:space="preserve">
<style type="text/css">
.st0{fill:#000000;}
</style>
<g>
<polygon class="st0" points="93.539,218.584 275.004,218.584 354.699,138.894 355.448,138.145 355.448,125.045 93.539,125.045 "/>
<polygon class="st0" points="402.213,433.724 46.77,433.724 46.77,78.276 402.213,78.276 402.213,91.467 448.983,56.572
448.983,31.506 0,31.506 0,480.494 448.983,480.494 448.983,289.204 402.213,335.974 "/>
<path class="st0" d="M229.358,274.708H93.539v28.062h120.476C218.602,292.858,223.932,283.312,229.358,274.708z"/>
<path class="st0" d="M93.539,349.539v28.062h110.935c-3.275-8.796-4.302-18.334-3.649-28.062H93.539z"/>
<path class="st0" d="M290.939,268.789c-15.501,15.501-55.612,80.76-40.11,96.27c15.51,15.51,80.76-24.609,96.27-40.11l63.755-63.77
l-56.155-56.15L290.939,268.789z"/>
<path class="st0" d="M500.374,115.509c-15.511-15.502-40.649-15.502-56.15,0l-76.682,76.685l56.156,56.15l76.676-76.685
C515.875,156.158,515.875,131.019,500.374,115.509z M400.166,202.361l-9.636-9.628l53.684-53.684l9.619,9.618L400.166,202.361z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 5.5 KiB

1
static/icons/gitea.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="0 0 512 512"><path d="M502.6 103.7c-3.3-3.3-7.8-3.3-7.8-3.3s-95.5 5.4-144.9 6.5c-10.8.2-21.6.5-32.3.6V203c-4.5-2.1-9-4.3-13.5-6.4 0-29.6-.1-88.9-.1-88.9-23.6.3-72.7-1.8-72.7-1.8s-115.2-5.8-127.7-6.9c-8-.5-18.3-1.7-31.8 1.2-7.1 1.5-27.3 6-43.8 21.9C-8.7 154.8.7 206.7 1.9 214.5c1.4 9.5 5.6 36 25.8 59 37.3 45.7 117.6 44.6 117.6 44.6s9.9 23.5 24.9 45.2c20.4 27 41.3 48 61.7 50.5 51.3 0 153.9-.1 153.9-.1s9.8.1 23-8.4c11.4-6.9 21.6-19.1 21.6-19.1s10.5-11.2 25.2-36.9c4.5-7.9 8.2-15.6 11.5-22.8 0 0 45-95.4 45-188.2-1-28-7.9-33-9.5-34.6M97.7 269.9c-21.1-6.9-30.1-15.2-30.1-15.2S52 243.8 44.2 222.3c-13.4-36-1.1-58-1.1-58s6.8-18.3 31.4-24.4c11.2-3 25.2-2.5 25.2-2.5s5.8 48.4 12.8 76.7c5.9 23.8 20.2 63.3 20.2 63.3s-21.3-2.6-35-7.5m289.4-4.5c-5.2 12.6-44.8 92.1-44.8 92.1s-5 11.8-16 12.5c-4.7.3-8.4-1-8.4-1s-.2-.1-4.3-1.7l-92-44.8s-8.9-4.6-10.4-12.7c-1.8-6.6 2.2-14.7 2.2-14.7l44.2-91.1s3.9-7.9 9.9-10.6c.5-.2 1.9-.8 3.7-1.2 6.6-1.7 14.7 2.3 14.7 2.3l18.4 8.9c-3.7 7.6-7.5 15.2-11.2 22.9-5.5-.1-10.5 2.9-13.1 7.7-2.8 5.1-2.2 11.5 1.5 16.1-6.6 13.8-13.3 27.5-19.9 41.1-6.7.1-12.5 4.7-14.1 11.2-1.5 6.5 1.6 13.3 7.4 16.3 6.3 3.3 14.3 1.5 18.5-4.4 4.2-5.8 3.5-13.8-1.5-18.8l19.5-40c1.2.1 3 .2 5-.4 3.3-.7 5.8-2.9 5.8-2.9 3.4 1.5 7 3.1 10.8 5 3.9 2 7.6 4 10.9 5.9.7.4 1.5.9 2.3 1.5 1.3 1.1 2.8 2.5 3.8 4.5 1.5 4.5-1.5 12.1-1.5 12.1-1.9 6.2-15 33.1-15 33.1-6.6-.2-12.5 4.1-14.4 10.2-2.1 6.6.9 14.1 7.2 17.3 6.4 3.3 14.2 1.4 18.3-4.3 4.1-5.5 3.7-13.3-.9-18.4l4.6-9.2c4.1-8.5 11-24.8 11-24.8.7-1.4 4.6-8.4 2.2-17.3-2-9.3-10.3-13.6-10.3-13.6-9.9-6.4-23.8-12.4-23.8-12.4s0-3.3-.9-5.8-2.3-4.2-3.2-5.1c3.6-7.6 7.4-15.1 11-22.6l61.8 29.9s10.3 4.6 12.5 13.2c1.5 6-.4 11.4-1.5 14" style="fill:#fff"/></svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

1
static/icons/github.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="0 0 512 512"><path d="M256 6.3C114.6 6.3 0 120.9 0 262.3c0 113.3 73.3 209 175 242.9 12.8 2.2 17.6-5.4 17.6-12.2 0-6.1-.3-26.2-.3-47.7-64.3 11.8-81-15.7-86.1-30.1-2.9-7.4-15.4-30.1-26.2-36.2-9-4.8-21.8-16.6-.3-17 20.2-.3 34.6 18.6 39.4 26.2 23 38.7 59.8 27.8 74.6 21.1 2.2-16.6 9-27.8 16.3-34.2-57-6.4-116.5-28.5-116.5-126.4 0-27.8 9.9-50.9 26.2-68.8-2.6-6.4-11.5-32.6 2.6-67.8 0 0 21.4-6.7 70.4 26.2 20.5-5.8 42.2-8.6 64-8.6s43.5 2.9 64 8.6c49-33.3 70.4-26.2 70.4-26.2 14.1 35.2 5.1 61.4 2.6 67.8 16.3 17.9 26.2 40.6 26.2 68.8 0 98.2-59.8 120-116.8 126.4 9.3 8 17.3 23.4 17.3 47.4 0 34.2-.3 61.8-.3 70.4 0 6.7 4.8 14.7 17.6 12.2C438.7 471.3 512 375.3 512 262.3c0-141.4-114.6-256-256-256" style="fill-rule:evenodd;clip-rule:evenodd;fill:#fff"/></svg>

After

Width:  |  Height:  |  Size: 819 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="0 0 512 512"><path d="M455.1 0H56.9C25.5 0 0 25.5 0 56.9v398.2C0 486.5 25.5 512 56.9 512h398.2c31.4 0 56.9-25.5 56.9-56.9V56.9C512 25.5 486.5 0 455.1 0M154.8 440.9H78.5V194.4h76.4v246.5zm-38.5-278.8c-24.9 0-45.2-20.4-45.2-45.5s20.2-45.5 45.2-45.5 45.1 20.4 45.1 45.5-20.2 45.5-45.1 45.5m324.6 278.8h-76V311.5c0-35.5-13.5-55.3-41.6-55.3-30.5 0-46.5 20.6-46.5 55.3v129.4h-73.2V194.4h73.2v33.2s22-40.7 74.3-40.7 89.7 31.9 89.7 98v156z" style="fill-rule:evenodd;clip-rule:evenodd;fill:#fff"/></svg>

After

Width:  |  Height:  |  Size: 564 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="0 0 512 512"><path d="M494.3 113.4C486.9 58.3 439 15 382.1 6.6 372.5 5.2 336.2 0 252 0h-.6c-84.2 0-102.2 5.2-111.8 6.6-55.3 8.2-105.7 47.1-118 102.8-5.9 27.4-6.5 57.8-5.4 85.7 1.6 40 1.9 79.9 5.5 119.7 2.5 26.4 6.9 52.7 13.1 78.5 11.6 47.7 58.7 87.4 104.9 103.6 49.4 16.9 102.6 19.7 153.5 8.1 5.6-1.3 11.1-2.8 16.6-4.5 12.4-3.9 26.9-8.3 37.5-16.1.1-.1.3-.2.4-.4s.1-.3.1-.5v-38.6c0-.2 0-.3-.1-.5s-.2-.3-.3-.4-.3-.2-.5-.2h-.5c-32.6 7.8-66.1 11.7-99.6 11.6-57.7 0-73.2-27.4-77.7-38.8-3.6-9.9-5.8-20.1-6.7-30.6 0-.2 0-.4.1-.5.1-.2.2-.3.3-.4s.3-.2.5-.2h.5c32.1 7.7 65 11.6 98 11.6 7.9 0 15.8 0 23.8-.2 33.2-.9 68.2-2.6 100.8-9 .8-.2 1.6-.3 2.3-.5 51.5-9.9 100.5-40.9 105.5-119.5.2-3.1.7-32.4.7-35.6-.1-11 3.4-77.5-.6-118.3m-81.6 198.5h-54.2V179.2c0-27.9-11.6-42.2-35.3-42.2-26 0-39.1 16.8-39.1 50.1v72.6h-53.8v-72.6c0-33.3-13.1-50.1-39.1-50.1-23.5 0-35.3 14.2-35.3 42.2v132.6h-54.1V175.2c0-27.9 7.1-50.1 21.4-66.6 14.7-16.4 34-24.8 58-24.8 27.7 0 48.7 10.7 62.6 32l13.5 22.6 13.5-22.6c14-21.3 34.9-32 62.6-32 23.9 0 43.2 8.4 58 24.8q21.3 24.6 21.3 66.6z" style="fill:#fff"/></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

1
static/icons/matrix.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="0 0 512 512"><path d="M465.3 499.7V11.8h-35V.1h48.6V512h-48.6v-11.7zM163.4 167v24.6h.7c6.2-9 14.3-16.5 23.8-21.9 9.3-5.2 20-7.8 31.8-7.8 11.5 0 22.1 2.2 31.5 6.7 9.5 4.5 16.8 12.3 21.8 23.7 5.4-8 12.7-15.1 22.1-21.1 9.3-6.1 20.3-9.2 33-9.2 9.6 0 18.6 1.2 26.7 3.5 8.2 2.4 15.3 6.1 21.1 11.3 5.9 5.2 10.4 11.9 13.7 20.3s4.9 18.4 4.9 30.2v122.1h-50.1V246.1c0-6.1-.2-11.9-.7-17.3-.3-4.9-1.6-9.7-3.9-14.1-2.1-4-5.4-7.3-9.3-9.5-4.1-2.3-9.7-3.5-16.8-3.5-7 0-12.7 1.4-17.1 4-4.4 2.7-7.8 6.2-10.2 10.6-2.5 4.6-4.2 9.6-4.9 14.8q-1.2 8.4-1.2 16.8v101.6h-50.1V247.1c0-5.4-.1-10.8-.3-16-.2-5-1.2-10-3-14.7-1.7-4.4-4.8-8.2-8.8-10.8-4.1-2.7-10.2-4-18.2-4-3.2.1-6.3.7-9.3 1.6-4.1 1.2-8 3.2-11.3 6-3.6 2.9-6.8 7.2-9.3 12.7-2.6 5.5-3.9 12.8-3.9 21.8v105.9h-50.2V167.2zM46.7 12.3v487.9h35v11.7H33.1V0h48.5v11.7z" style="fill:#fff"/></svg>

After

Width:  |  Height:  |  Size: 890 B

View File

@@ -0,0 +1,7 @@
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Transformed by: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="-10 -5 1034 1034" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" fill="#000000">
<g id="SVGRepo_bgCarrier" stroke-width="0"/>

After

Width:  |  Height:  |  Size: 845 B

1
static/icons/untappd.svg Normal file
View File

@@ -0,0 +1 @@
<?xml version="1.0"?><svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title/><path d="M11 13.299l-5.824 8.133c-.298.416-.8.635-1.308.572-.578-.072-1.374-.289-2.195-.879S.392 19.849.139 19.323a1.402 1.402 0 0 1 .122-1.425l5.824-8.133a3.066 3.066 0 0 1 1.062-.927l1.146-.604c.23-.121.436-.283.608-.478.556-.631 2.049-2.284 4.696-4.957l.046-.212a.134.134 0 0 1 .096-.1l.146-.037a.135.135 0 0 0 .101-.141l-.015-.18a.13.13 0 0 1 .125-.142c.176-.005.518.046 1.001.393s.64.656.692.824a.13.13 0 0 1-.095.164l-.175.044a.133.133 0 0 0-.101.141l.012.15a.131.131 0 0 1-.063.123l-.186.112c-1.679 3.369-2.764 5.316-3.183 6.046a2.157 2.157 0 0 0-.257.73l-.205 1.281A3.074 3.074 0 0 1 11 13.3zm12.739 4.598l-5.824-8.133a3.066 3.066 0 0 0-1.062-.927l-1.146-.605a2.138 2.138 0 0 1-.608-.478 50.504 50.504 0 0 0-.587-.654.089.089 0 0 0-.142.018 97.261 97.261 0 0 1-1.745 3.223 1.42 1.42 0 0 0-.171.485 3.518 3.518 0 0 0 0 1.103l.01.064c.075.471.259.918.536 1.305l5.824 8.133c.296.413.79.635 1.294.574a4.759 4.759 0 0 0 2.209-.881 4.762 4.762 0 0 0 1.533-1.802 1.4 1.4 0 0 0-.122-1.425zM8.306 3.366l.175.044a.134.134 0 0 1 .101.141l-.012.15a.13.13 0 0 0 .063.123l.186.112c.311.623.599 1.194.869 1.721.026.051.091.06.129.019.437-.469.964-1.025 1.585-1.668a.137.137 0 0 0 .003-.19c-.315-.322-.645-.659-1.002-1.02l-.046-.212a.13.13 0 0 0-.096-.099l-.146-.037a.135.135 0 0 1-.101-.141l.015-.18a.13.13 0 0 0-.123-.142c-.175-.005-.518.045-1.002.393-.483.347-.64.656-.692.824a.13.13 0 0 0 .095.164z"/></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
static/img/homelab.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

939
yarn.lock

File diff suppressed because it is too large Load Diff