Compare commits

...

5 Commits

Author SHA1 Message Date
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
13 changed files with 1188 additions and 34 deletions

View File

@ -0,0 +1,101 @@
---
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>
```

View File

View File

@ -1,9 +1,29 @@
--- ---
sidebar_position: 1 sidebar_position: 1
title: Overview
--- ---
# What is it? ## What is it?
This is my project of publicly available documentation of my home servers and services. This is my project of publicly available documentation of my home servers and self-hosted services.
Working on it... ## Network
The gate to my HomeLab is a **UniFi Cloud Gateway Ultra**. It is connected to a **1 Gbps** fiber optic from my ISP and manages **3 static WAN IP** addresses.
The local network is separated into **four VLANs**.
The gateway is also a DNS server for all local network and VPN clients.
WiFi network is delivered by **two UniFi U6+** access points powered with the **Switch Lite 8 PoE**.
[More on network](network.md)
## Servers
My family home cloud is provided by the **Synology DS423+**. It is for photos and documents hosting and sharing.
I also have a **DIY NAS with TrueNAS Community Edition** on it that hosts most of the services for personal and family use, that are not from Synology.
The third one is the **Asus PN42** min PC with an Intel N100 CPU with the **Proxomox VE** on it. It hosts public services, like this website, my Gitea instance, and others.
I also have a mighty **Home Assistant Blue** with... well **Home Assistant** on it. It does not depend on other servers and has a separate Cloudflare tunnel to it from the outside to be available even when all other servers fail.

84
docs/homelab/network.md Normal file
View File

@ -0,0 +1,84 @@
---
title: Network
---
## WAN
### Port forwarding
```mermaid
---
config:
look: handDrawn
theme: neutral
---
flowchart LR
W8[WAN IP *8]
W9[WAN IP *9]
W0[WAN IP *0]
montgomery("`Synology NAS
_DSM Web UI, Hyper Backup Vault, Drive Server_`")
plex(Plex external access)
ingress50("`ingress-50
_Zoraxy_`")
ingress1("`ingress-1
_Zoraxy_`")
WAN1 --> W8
WAN1 --> W9
WAN1 --> W0
W8 --> montgomery
W8 --> plex
W8 --> qbt(qBittorrent)
W9 --> gitssh(Gitea SSH)
W9 --> ingress50 --> pub(Public services)
W0 --> ingress1 --> per(Personal services)
```
### Firewall rules
In addition to default rules.
| Name | Action | Source Zone | Destination Zone |
|-------------------------- | ------ | ------------- | ---------------- |
| Allow UniFi remote access | Allow | External | Gateway |
## Local network
### VLANs
| Name | Subnet | Description | Isolate network |
|------------ | ----------------- | ------------------------------------------------------------- | --------------- |
| **Default** | _192.168.1.0/24_ | Default local network for laptops, family phones and tablets | No |
| **Pub** | _192.168.50.0/24_ | An isolated VLAN for public services | No |
| **Guest** | _192.168.5.0/24_ | An isolated VLAN for guest WiFi access | No |
| **IoT** | _192.168.6.0/24_ | An isolated VLAN for connected home appliance | No |
- Device Isolation is disabled for all networks
### Firewall zones
| Name | Built in | Networks / Interfaces |
|---------------- | -------- | ------------------------------------------- |
| Internal | âś… | [`Default`](#vlans) |
| External | âś… | [`Primary (WAN1)`](#wan) `Secondary (WAN2)` |
| Gateway | âś… | - |
| VPN | âś… | [`Hearthstone`](#vpn) [`VPS`](#vpn) |
| Hotspot | âś… | [`Guest`](#vlans) |
| DMZ | âś… | - |
| VLAN 50 | ❌ | [`Pub`](#vlans) |
| VLAN 6 | ❌ | [`IoT`](#vlans) |
### Zones access rules
Additional Firewall rules allowing or blocking zone-to-zone or subnet-to-subnet communications.
| Source Zone | Destination Zone | Source | Destination | Action | Description |
|-------------- | ---------------- | --------------------- | --------------------------- | ------------------ | ---------------------------------------------------------------------------------- |
| Internal | VLAN 50 | All | All | Allow with return | Allow all traffic from [`Default`](#vlans) network to [`Pub`](#vlans) |
| Internal | VLAN 6 | All | All | Allow with return | Allow all traffic from [`Default`](#vlans) network to [`IoT`](#vlans) |
| VPN | Internal | [VPS subnet](#vpn) | All | Allow only return | Allow return traffic from [`VPS`](#vpn) subnet to [`Default`](#vlans) |
| VPN | Internal | [VPS subnet](#vpn) | All | Block | Block [`VPS`](#vpn) VPN clients from accessing the [`Default`](#vlans) network |
| VPN | Hotspot | [VPS subnet](#vpn) | All | Block | Block [`VPS`](#vpn) VPN clients from accessing the [`Guest`](#vlans) network |
| VPN | DMZ | [VPS subnet](#vpn) | All | Block | Block [`VPS`](#vpn) VPN clients from accessing the [`DMZ`](#firewall-zones) zone |
| VPN | VLAN 50 | All | [Hearthstone](#vpn) | Allow all | Allow [`Hearthstone`](#vpn) VPN clients access to [`Pub`](#vlans) network |
| VPN | VLAN 6 (IoT) | All | [Hearthstone](#vpn) | Allow all | Block [`Hearthstone`](#vpn) VPN clients access to [`IoT`](#vlans) network |
| VLAN 50 | VLAN 50 | All | All | Allow all | Allow [`Pub`](#vlans) network clients accessing each other |
## VPN
There are two Wireguard servers configured:
1. **Hearthstone**. Subnet _192.168.3.0/24_. For external access to all local networks.
1. **VPS**. Subnet _192.168.4.0/24_. For accessing VPS servers as local network devices.

View File

@ -36,6 +36,12 @@ const config = {
locales: ['en'], locales: ['en'],
}, },
markdown: {
mermaid: true,
},
themes: ['@docusaurus/theme-mermaid'],
scripts: [ scripts: [
{ {
src: 'https://plausible.nicelycomposed.codes/js/script.outbound-links.js', src: 'https://plausible.nicelycomposed.codes/js/script.outbound-links.js',
@ -56,6 +62,9 @@ const config = {
showReadingTime: true, showReadingTime: true,
feedOptions: { feedOptions: {
type: ['rss', 'atom'], type: ['rss', 'atom'],
title: "Yehor Vialov's Blog",
description: 'Some notes, interesting things and projects',
copyright: 'Copyright © ${new Date().getFullYear()} Yehor Vialov',
xslt: true, xslt: true,
}, },
blogSidebarTitle: 'Timeline', blogSidebarTitle: 'Timeline',
@ -112,6 +121,14 @@ const config = {
label: 'Blog', label: 'Blog',
to: '/blog', to: '/blog',
}, },
{
label: 'Blog RSS feed',
to: 'pathname:///blog/rss.xml',
},
{
label: 'Blog Atom feed',
to: 'pathname:///blog/atom.xml',
},
], ],
}, },
{ {

View File

@ -16,6 +16,7 @@
"dependencies": { "dependencies": {
"@docusaurus/core": "3.7.0", "@docusaurus/core": "3.7.0",
"@docusaurus/preset-classic": "3.7.0", "@docusaurus/preset-classic": "3.7.0",
"@docusaurus/theme-mermaid": "^3.7.0",
"@mdx-js/react": "^3.0.0", "@mdx-js/react": "^3.0.0",
"clsx": "^2.0.0", "clsx": "^2.0.0",
"prism-react-renderer": "^2.3.0", "prism-react-renderer": "^2.3.0",
@ -41,4 +42,4 @@
"engines": { "engines": {
"node": ">=18.0" "node": ">=18.0"
} }
} }

View File

@ -17,9 +17,8 @@
const sidebars = { const sidebars = {
homelabSidebar: [{ homelabSidebar: [{
type: 'doc', type: 'autogenerated',
id: 'homelab/index', dirName: 'homelab',
label: 'HomeLab',
},], },],

View File

@ -3,16 +3,6 @@ import Heading from '@theme/Heading';
import styles from './styles.module.css'; import styles from './styles.module.css';
const FeatureList = [ 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', title: 'Blog',
link: 'blog', link: 'blog',
@ -23,7 +13,16 @@ 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 self-hosted services.
</>
),
},
]; ];
function Feature({ Svg, title, link, description }) { function Feature({ Svg, title, link, description }) {

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,9 +13,9 @@ function HomepageHeader() {
<header className={clsx('hero hero--primary', styles.heroBanner)}> <header className={clsx('hero hero--primary', styles.heroBanner)}>
<div className="container"> <div className="container">
<Heading as="h1" className="hero__title"> <Heading as="h1" className="hero__title">
{siteConfig.title} Yehor Vialov
</Heading> </Heading>
<p className="hero__subtitle">{siteConfig.tagline}</p> <p className="hero__subtitle">Public Profiles</p>
<div className={styles.buttons}> <div className={styles.buttons}>
<Link <Link
className="button button--secondary button--lg" className="button button--secondary button--lg"

View File

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

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