mirror of
https://codeberg.org/postscriptum/gemlog.git
synced 2026-02-19 06:22:41 +00:00
initial commit
This commit is contained in:
commit
259fee630b
127 changed files with 7811 additions and 0 deletions
33
public/en/briar-collection.gmi
Normal file
33
public/en/briar-collection.gmi
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
# Briar collection
|
||||
|
||||
## Stanwell
|
||||
|
||||
### No.98, Relief Lovat, Sand
|
||||
|
||||
=> https://www.danishpipeshop.com/d/Stanwell-Relief-98-Lovat-Sand-i30424.html The Danish Pipe Shop
|
||||
|
||||
### No.107, Royal Guard, Petit Billard
|
||||
|
||||
=> https://www.danishpipeshop.com/d/Stanwell-Royal-Guard-107-Petit-Billard-i1327.html The Danish Pipe Shop
|
||||
|
||||
## Georg Jensen
|
||||
|
||||
### No.35
|
||||
|
||||
=> https://www.danishpipeshop.com/d/Estate-My-Own-Blend-Billard-Presmoked-i31145.html The Danish Pipe Shop
|
||||
|
||||
### No.43
|
||||
|
||||
=> https://www.danishpipeshop.com/d/Estate-Georg-Jensen-Granat-Bent-Billard-Presmok-i31375.html The Danish Pipe Shop
|
||||
|
||||
## Savinelli
|
||||
|
||||
### No.628, Oscar Tiger
|
||||
|
||||
=> https://b2b.savinelli.it/savinelli-oscar-tiger-rusticata-628-p104tz-628.html Official Website
|
||||
|
||||
## Tsuge
|
||||
|
||||
### Bamboo
|
||||
|
||||
=> https://tsugepipe.co.jp/1/13/ツゲ・バンブー・ストレート・サンド/ Official Website
|
||||
13
public/en/build-lagrange-with-webp-and-mpeg-support.gmi
Normal file
13
public/en/build-lagrange-with-webp-and-mpeg-support.gmi
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
# Build Lagrange with WEBP and MPEG support
|
||||
|
||||
``` bash
|
||||
apt install git cmake zip libsdl2-dev libssl-dev libpcre3-dev zlib1g-dev libunistring-dev libfribidi-dev libmpg123-dev
|
||||
git clone --recursive --branch release https://git.skyjake.fi/gemini/lagrange
|
||||
cd lagrange
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_BUILD_TYPE=Release -DENABLE_WEBP=YES -DENABLE_MPG123=YES
|
||||
cmake --build .
|
||||
chmod +x lagrange
|
||||
./lagrange
|
||||
```
|
||||
9
public/en/cli-gemini-cheat-sheet.gmi
Normal file
9
public/en/cli-gemini-cheat-sheet.gmi
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
# CLI Gemini cheat sheet
|
||||
|
||||
### Get raw server response
|
||||
|
||||
``` bash
|
||||
echo -e "gemini://gemini.circumlunar.space:1965/\r\n" | openssl s_client -connect gemini.circumlunar.space:1965 -ign_eof
|
||||
```
|
||||
|
||||
=> gemini://bbs.geminispace.org/u/stack/25283 Source
|
||||
44
public/en/connect-i2p-with-yggdrasil.gmi
Normal file
44
public/en/connect-i2p-with-yggdrasil.gmi
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
# Connect I2P with Yggdrasil
|
||||
|
||||
Access the I2P network without installing its i2pd router.
|
||||
|
||||
## FireFox / LibreWolf
|
||||
|
||||
### PAC file
|
||||
|
||||
Settings > Network Settings > Automatic proxy configuration URL > file:///path/to/route.pac
|
||||
|
||||
``` route.pac
|
||||
function FindProxyForURL(url, host)
|
||||
{
|
||||
if (/\.(i2p|onion)$/.test(host))
|
||||
{
|
||||
// HTTP
|
||||
return 'PROXY [324:71e:281a:9ed3::fa11]:3128';
|
||||
|
||||
// SOCKS5
|
||||
// return 'SOCKS5 [324:71e:281a:9ed3::fa11]:1080';
|
||||
}
|
||||
}
|
||||
```
|
||||
* an example above uses the outproxy.acetone.*
|
||||
|
||||
### DNS
|
||||
|
||||
Enter to the URL `about:config`, then add following records:
|
||||
|
||||
* browser.fixup.domainsuffixwhitelist.i2p
|
||||
* browser.fixup.domainsuffixwhitelist.onion
|
||||
|
||||
### Test
|
||||
|
||||
=> http://proxy4uwdijqxac2bvdx4fuhem6njmiwukuk2gelejv2nzxka2xq.b32.i2p
|
||||
|
||||
## Feedback
|
||||
|
||||
=> gemini://bbs.geminispace.org/s/Yggdrasil/29406 Discussion on BBS
|
||||
=> http://[302:68d0:f0d5:b88d::fed]/ps/p/1750540695.117515 Comment on the Fediverse instance
|
||||
|
||||
## See also
|
||||
|
||||
=> connect-libera-chat-with-yggdrasil.gmi Connect Libera.Chat with Yggdrasil
|
||||
40
public/en/connect-libera-chat-with-yggdrasil.gmi
Normal file
40
public/en/connect-libera-chat-with-yggdrasil.gmi
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
# Connect Libera.Chat with Yggdrasil
|
||||
|
||||
## Proxy
|
||||
|
||||
I didn't find any official Libera.Chat API for this network:
|
||||
=> https://libera.chat/guides/connect
|
||||
|
||||
### Halloy
|
||||
|
||||
Halloy - is the modern IRC client, written in Rust:
|
||||
=> https://halloy.chat
|
||||
|
||||
The configuration example below uses Acetone's SOCKS5 proxy:
|
||||
=> http://[324:71e:281a:9ed3::fa11]
|
||||
|
||||
TLS option is not required here, as Yggdrasil provides encrypted end-to-end connections out of the box.
|
||||
|
||||
``` config.toml
|
||||
[servers.libera]
|
||||
nickname = "NAME"
|
||||
server = "irc.libera.chat"
|
||||
port = 6667
|
||||
use_tls = false
|
||||
channels = ["#yggdrasil","#misfin"]
|
||||
|
||||
[proxy.socks5]
|
||||
host = "324:71e:281a:9ed3::fa11"
|
||||
port = 1080
|
||||
```
|
||||
* replace `nickname` and `channels` with your value
|
||||
|
||||
## Feedback
|
||||
|
||||
=> gemini://bbs.geminispace.org/s/Yggdrasil/29597 Discussion on BBS
|
||||
=> https://wizard.casa/post/0197a9cd-abaf-7949-f53c-2e0b25d0ba13 Comment on the Fediverse (Internet) instance
|
||||
=> http://[302:68d0:f0d5:b88d::fed]/ps/p/1750900519.824742 Comment on the Fediverse (Yggdrasil) instance
|
||||
|
||||
## See also
|
||||
|
||||
=> connect-i2p-with-yggdrasil.gmi Connect I2P with Yggdrasil
|
||||
10
public/en/connect-remote-storage-in-vlc-with-sftp.gmi
Normal file
10
public/en/connect-remote-storage-in-vlc-with-sftp.gmi
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
# Connect remote storage in VLC with SFTP
|
||||
|
||||
``` ~/.config/vlc/vlcrc
|
||||
sftp-port=22
|
||||
sftp-user=user
|
||||
sftp-pwd=password
|
||||
```
|
||||
|
||||
* Ctrl+N to open network connection
|
||||
* Ctrl+L to open playlist menu
|
||||
14
public/en/create-local-website-mirror-using-wget.gmi
Normal file
14
public/en/create-local-website-mirror-using-wget.gmi
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
# Create local website mirror using wget
|
||||
|
||||
``` bash
|
||||
wget -mpEk "url"
|
||||
```
|
||||
|
||||
## Assets
|
||||
|
||||
### zabytki.in.ua
|
||||
|
||||
``` bash
|
||||
wget -mpEk --domains=pbs.twimg.com --wait=1 https://zabytki.in.ua/community/
|
||||
```
|
||||
* --span-hosts is not an option here!
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
# CSS color-scheme in FireFox on FPR enabled
|
||||
|
||||
This CSS attribute ignored on the `resistFingerprinting` option is enabled in FireFox / LibreWolf:
|
||||
|
||||
``` css
|
||||
color-scheme: light dark;
|
||||
```
|
||||
|
||||
To resolve, I'm using following asset in the `about:config`:
|
||||
|
||||
```
|
||||
privacy.resistFingerprinting = false
|
||||
privacy.fingerprintingProtection = true
|
||||
privacy.fingerprintingProtection.overrides = +AllTargets,-CSSPrefersColorScheme
|
||||
```
|
||||
|
||||
=> https://bugzilla.mozilla.org/show_bug.cgi?id=1732114
|
||||
21
public/en/custom-dns-resolver-on-debian-12.gmi
Normal file
21
public/en/custom-dns-resolver-on-debian-12.gmi
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
# Custom DNS resolver on Debian 12
|
||||
|
||||
Add name server:
|
||||
|
||||
``` /etc/resolv.conf
|
||||
nameserver xx.xx.xx.xx
|
||||
```
|
||||
|
||||
Disable settings overwrite on system reboot:
|
||||
|
||||
``` /etc/dhcp/dhclient.conf
|
||||
# domain-name, domain-name-servers, domain-search, host-name,
|
||||
# dhcp6.name-servers, dhcp6.domain-search, dhcp6.fqdn, dhcp6.sntp-servers,
|
||||
```
|
||||
|
||||
Alternatively:
|
||||
|
||||
``` /etc/NetworkManager/NetworkManager.conf
|
||||
[main]
|
||||
dns=none
|
||||
```
|
||||
30
public/en/dark-theme-support-in-gtk-3-apps.gmi
Normal file
30
public/en/dark-theme-support-in-gtk-3-apps.gmi
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
# Dark theme support in GTK 3 apps
|
||||
|
||||
Some old applications, like Rhythmbox, do not support the GTK 4 / Adwaita theme on modern distributions like Fedora.
|
||||
|
||||
Even though there are many solutions available,
|
||||
I'm using this simple fix that requires just an application restart after making the change:
|
||||
|
||||
``` ~/.config/gtk-3.0/settings.ini
|
||||
[Settings]
|
||||
gtk-application-prefer-dark-theme=1
|
||||
```
|
||||
|
||||
## Integrations
|
||||
|
||||
### CSS patch for i3wm
|
||||
|
||||
Also, found this file in my backup folder, so let's keep it here, as it may be needed elsewhere (suppose in i3wm case)
|
||||
|
||||
``` ~/.config/gtk-3.0/gtk.css
|
||||
.window-frame {
|
||||
box-shadow: none;
|
||||
margin: 0;
|
||||
}
|
||||
```
|
||||
|
||||
### Adwaita theme port
|
||||
|
||||
Personally, I'm not using it, but it would be helpful at some point:
|
||||
|
||||
=> https://github.com/lassekongo83/adw-gtk3
|
||||
17
public/en/disable-led-on-hator-htm-312.gmi
Normal file
17
public/en/disable-led-on-hator-htm-312.gmi
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# Disable LED on Hator HTM-312
|
||||
|
||||
Got this used mouse for free.
|
||||
|
||||
Shining rainbow there distracting, and official documentation say nothing about how to setup but additional software installation for Windows.
|
||||
|
||||
Here is solution to switch or turn off the LED mode, brute forced by random combinations:
|
||||
|
||||
* press middle wheel button
|
||||
* then click left button
|
||||
* then forward button
|
||||
|
||||
## Experience
|
||||
|
||||
I like the clickers in this mouse but can't use it. On scrolling up, wheel sounds ugly, so that is hardware issue I can't resolve.
|
||||
|
||||
Best choice for PC is Logitech.
|
||||
13
public/en/disable-new-windows-auto-focus-in-gnome.gmi
Normal file
13
public/en/disable-new-windows-auto-focus-in-gnome.gmi
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
# Disable new windows auto-focus in GNOME
|
||||
|
||||
``` bash
|
||||
gsettings set org.gnome.desktop.wm.preferences focus-new-windows 'strict'
|
||||
```
|
||||
|
||||
optionally:
|
||||
|
||||
``` bash
|
||||
gsettings set org.gnome.desktop.wm.preferences auto-raise 'true'
|
||||
```
|
||||
|
||||
see also dconf-editor GUI.
|
||||
5
public/en/enable-archive-context-menu-in-thunar.gmi
Normal file
5
public/en/enable-archive-context-menu-in-thunar.gmi
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
# Enable archive context menu in Thunar
|
||||
|
||||
``` bash
|
||||
apt install thunar-archive-plugin
|
||||
```
|
||||
37
public/en/favorite-computer-games.gmi
Normal file
37
public/en/favorite-computer-games.gmi
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
# Favorite computer games
|
||||
|
||||
## SEGA
|
||||
|
||||
* Aladdin
|
||||
* Desert Strike
|
||||
* Dune
|
||||
* Ecco the Dolphin
|
||||
* Mortal Combat
|
||||
* Sonic
|
||||
* Taz-Mania
|
||||
* The Lion King
|
||||
* WWF Wrestlemania
|
||||
|
||||
## PS
|
||||
|
||||
* Parasite Eve 2
|
||||
* Silent Hill
|
||||
|
||||
## PC
|
||||
|
||||
* Cabela's 4x4 Off-Road Adventure
|
||||
* Disciples 2
|
||||
* Fallout 2
|
||||
* Ghotic
|
||||
* GTA Vice City
|
||||
* Hitman
|
||||
* IL-2
|
||||
* Mafia 1
|
||||
* Postal 2
|
||||
* Richard Burns Rally
|
||||
* Vampire: The Masquerade – Bloodlines
|
||||
* War Thunder
|
||||
|
||||
## Mobile
|
||||
|
||||
* TES Legends
|
||||
25
public/en/favorite-movies.gmi
Normal file
25
public/en/favorite-movies.gmi
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
# Favorite movies
|
||||
|
||||
## 2021
|
||||
|
||||
=> https://www.imdb.com/title/tt12322986/ Petite nature (Softie)
|
||||
|
||||
## 2019
|
||||
|
||||
=> https://www.imdb.com/title/tt7286456/ Joker
|
||||
|
||||
## 2003
|
||||
|
||||
=> https://www.imdb.com/title/tt0364569/ Oldeuboi (Oldboy)
|
||||
|
||||
## 2002
|
||||
|
||||
=> https://www.imdb.com/title/tt0253474/ The Pianist
|
||||
|
||||
## 1994
|
||||
|
||||
=> https://www.imdb.com/title/tt0110413/ Léon
|
||||
|
||||
## 1980
|
||||
|
||||
=> https://www.imdb.com/title/tt0080455/ The Blues Brothers
|
||||
95
public/en/favorite-music.gmi
Normal file
95
public/en/favorite-music.gmi
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
# Favorite music
|
||||
|
||||
## Clann
|
||||
|
||||
Dark Ambient, Dream-Pop
|
||||
|
||||
=> https://hy-records.com/pages/clann Official website
|
||||
|
||||
## Burshtyn
|
||||
|
||||
Black Metal
|
||||
|
||||
=> https://uk.wikipedia.org/wiki/Burshtyn Wikipedia
|
||||
=> favorite-music/burshtyn.gmi Best
|
||||
|
||||
## Igorrr
|
||||
|
||||
Alternative, Electronic, Rock
|
||||
|
||||
=> https://igorrr.com/ Official website
|
||||
=> favorite-music/igorrr.gmi Best
|
||||
|
||||
## Kate Tempest
|
||||
|
||||
Hip-Hop, Spoken-Word
|
||||
|
||||
=> https://www.kaetempest.co.uk/ Official website
|
||||
|
||||
## Kauan
|
||||
|
||||
Ambient, Doom Metal, Post-Rock
|
||||
|
||||
=> https://kauanmusic.com/ Official website
|
||||
=> favorite-music/kauan.gmi Best
|
||||
|
||||
## Lorde
|
||||
|
||||
Pop, Indie
|
||||
|
||||
=> https://www.lorde.co.nz/ Official website
|
||||
|
||||
## Meg Myers
|
||||
|
||||
Pop, Indie, Rock
|
||||
|
||||
=> http://megmyers.com/ Official website
|
||||
|
||||
### Best
|
||||
|
||||
=> https://music.youtube.com/watch?v=Xvh_0CuMMtM Heart Heart Head (2013)
|
||||
|
||||
## Nina Hagen
|
||||
|
||||
Punk, Post-Punk
|
||||
|
||||
=> https://en.wikipedia.org/wiki/Nina_Hagen Wikipedia
|
||||
|
||||
## Placebo
|
||||
|
||||
Alternative, Rock
|
||||
|
||||
=> https://www.placeboworld.co.uk/ Official website
|
||||
|
||||
## Rubio
|
||||
|
||||
Indie, Pop
|
||||
|
||||
=> https://music.youtube.com/channel/UCciW7qvUK5molS0SiZE4f4A Youtube Music Channel
|
||||
|
||||
### Best
|
||||
|
||||
=> https://music.youtube.com/watch?v=SQR1zzpjlHU Árboles (2018)
|
||||
|
||||
## Pačess
|
||||
|
||||
Punk, Metal
|
||||
|
||||
=> https://www.pacess.cz/ Official website
|
||||
=> favorite-music/pacess.gmi Best
|
||||
|
||||
## Steve Roach
|
||||
|
||||
Ambient, Electronic
|
||||
|
||||
=> https://steveroach.bandcamp.com/ BandCamp
|
||||
|
||||
## Till Lindemann
|
||||
|
||||
Electro-industrial, Industrial metal, Neue Deutsche Härte
|
||||
|
||||
=> https://www.rammstein.de/ Official website
|
||||
|
||||
### Best
|
||||
|
||||
=> https://www.youtube.com/watch?v=hPdDFx89fRs Übers Meer
|
||||
22
public/en/favorite-music/burshtyn.gmi
Normal file
22
public/en/favorite-music/burshtyn.gmi
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
# Burshtyn
|
||||
|
||||
Black Metal
|
||||
|
||||
=> https://uk.wikipedia.org/wiki/Burshtyn Wikipedia
|
||||
|
||||
## Best
|
||||
|
||||
### Безвірник (2017)
|
||||
|
||||
* 5000 Вердену
|
||||
* Коловорот
|
||||
* Тризуб мій стяг, тризуб мій горн
|
||||
|
||||
### Чортория (2020)
|
||||
|
||||
* Її Натхнення Пектораль
|
||||
* Сатанів
|
||||
|
||||
### Апокриф (2023)
|
||||
|
||||
* Гонтина
|
||||
15
public/en/favorite-music/igorrr.gmi
Normal file
15
public/en/favorite-music/igorrr.gmi
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
# Igorrr
|
||||
|
||||
Alternative, Electronic, Rock
|
||||
|
||||
=> https://igorrr.com/ Official website
|
||||
|
||||
## Best
|
||||
|
||||
### Moisissure (2009)
|
||||
|
||||
* Valse en Décomposition
|
||||
|
||||
### Savage Sinusoid (2017)
|
||||
|
||||
* Houmous
|
||||
26
public/en/favorite-music/kauan.gmi
Normal file
26
public/en/favorite-music/kauan.gmi
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
# Kauan
|
||||
|
||||
Ambient, Doom Metal, Post-Rock
|
||||
|
||||
=> https://kauanmusic.com/ Official website
|
||||
|
||||
## Best
|
||||
|
||||
### Kuu.. (2011)
|
||||
|
||||
* Ikuinen Junan Kulku
|
||||
* Suora Liila Sydänkäyrä
|
||||
|
||||
### Ice Fleet (2021)
|
||||
|
||||
* Maanpako
|
||||
|
||||
### Lumikuuro (Live, 2022)
|
||||
|
||||
* Lumikuuro
|
||||
* Äidin Laulu
|
||||
* Koivun Elämä
|
||||
|
||||
### ATM Revised (2023)
|
||||
|
||||
* Sokea Sisar
|
||||
13
public/en/favorite-music/pacess.gmi
Normal file
13
public/en/favorite-music/pacess.gmi
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
# Pačess
|
||||
|
||||
Punk, Metal
|
||||
|
||||
=> https://www.pacess.cz/ Official website
|
||||
|
||||
## Best
|
||||
|
||||
### Absolutno (2023)
|
||||
|
||||
* 33
|
||||
* Travěncové
|
||||
* Vavřín
|
||||
33
public/en/favorite-radio-stations.gmi
Normal file
33
public/en/favorite-radio-stations.gmi
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
# Favorite radio stations
|
||||
|
||||
## SomaFM
|
||||
|
||||
Over 30 unique channels of listener-supported, commercial-free, underground/alternative radio broadcasting to the world. All music hand-picked by SomaFM's award-winning DJs and music directors.
|
||||
|
||||
### Deep Space One
|
||||
|
||||
Deep ambient electronic, experimental and space music. Music for getting lost in space, or just exploring. Tracks with a tempo usually too slow for Space Station Soma, but too fast for Drone Zone.
|
||||
|
||||
=> https://somafm.com/deepspaceone
|
||||
|
||||
### SF 10-33
|
||||
|
||||
Live fire/police scanner audio from San Francisco processed and mixed with ambient and experimental music. A surreal audio zeitgeist of the city.
|
||||
|
||||
=> https://somafm.com/sf1033
|
||||
|
||||
### Seven Inch Soul
|
||||
|
||||
Drawing from the extensive vinyl collection of DJ Dion "The Watts" Garcia, you'll hear the greatest soul singles that were ever released... and with a few exceptions all are from the original vinyl 45rpm releases.
|
||||
|
||||
=> https://somafm.com/7soul
|
||||
|
||||
## Other
|
||||
|
||||
### Yggdrasil
|
||||
|
||||
=> http://[324:71e:281a:9ed3::ace]/ff-radio Pure Acetone's radio station
|
||||
|
||||
### Grand Theft Auto
|
||||
|
||||
* Vice City Radio (OST)
|
||||
38
public/en/favorite-series.gmi
Normal file
38
public/en/favorite-series.gmi
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
# Favorite series
|
||||
|
||||
## 2025
|
||||
|
||||
=> https://www.imdb.com/title/tt13623632/ Alien: Earth
|
||||
|
||||
## 2024
|
||||
|
||||
=> https://www.imdb.com/title/tt9892936/ Cien Años de Soledad (One Hundred Years of Solitude)
|
||||
|
||||
## 2023
|
||||
|
||||
=> https://www.imdb.com/title/tt21056886/ Scavengers Reign
|
||||
|
||||
## 2020
|
||||
|
||||
=> https://www.imdb.com/title/tt10048342/ The Queen's Gambit
|
||||
=> https://www.imdb.com/title/tt9815454/ Unorthodox
|
||||
|
||||
## 2019
|
||||
|
||||
=> https://www.imdb.com/title/tt8332438/ ZeroZeroZero
|
||||
|
||||
## 2013
|
||||
|
||||
=> https://www.imdb.com/title/tt2306299/ Vikings
|
||||
|
||||
## 2006
|
||||
|
||||
=> https://www.imdb.com/title/tt0487831/ The IT Crowd
|
||||
|
||||
## 2003
|
||||
|
||||
=> https://www.imdb.com/title/tt0903747/ Breaking Bad
|
||||
|
||||
## 1990
|
||||
|
||||
=> https://www.imdb.com/title/tt0096657/ Mr. Bean
|
||||
11
public/en/favorite-web.gmi
Normal file
11
public/en/favorite-web.gmi
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
# Favorite Web
|
||||
|
||||
Some bookmarks, as I never use the ones in my browser
|
||||
|
||||
## Art
|
||||
|
||||
=> https://streetartutopia.com/2025/05/07/stone-sculptures-by-jon-foreman/ 10 Spellbinding New Stone Sculptures by Jon Foreman (All from 2025)
|
||||
|
||||
## Homepages
|
||||
|
||||
=> http://mentallandscape.com/ Don P. Mitchell Homepage
|
||||
5
public/en/find-process-id-by-name.gmi
Normal file
5
public/en/find-process-id-by-name.gmi
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
# Find process ID by its name
|
||||
|
||||
``` bash
|
||||
pgrep keyword
|
||||
```
|
||||
7
public/en/firefox-config-notes.gmi
Normal file
7
public/en/firefox-config-notes.gmi
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
# Firefox config notes
|
||||
|
||||
Decode URL on address copy
|
||||
|
||||
``` about:config
|
||||
browser.urlbar.decodeURLsOnCopy:true
|
||||
```
|
||||
20
public/en/fix-fail2ban-service-launch-on-debian-12.gmi
Normal file
20
public/en/fix-fail2ban-service-launch-on-debian-12.gmi
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
# Fix fail2ban service launch on Debian 12
|
||||
|
||||
1. Add following lines into the jail configuration
|
||||
|
||||
``` /etc/fail2ban/jail.local
|
||||
[DEFAULT]
|
||||
backend = systemd
|
||||
```
|
||||
|
||||
2. Make sure python3-systemd was installed
|
||||
|
||||
``` bash
|
||||
apt install python3-systemd
|
||||
```
|
||||
|
||||
3. Restart service
|
||||
|
||||
``` bash
|
||||
systemctl restart fail2ban
|
||||
```
|
||||
9
public/en/fix-header-borders-in-gtk-apps-i3wm.gmi
Normal file
9
public/en/fix-header-borders-in-gtk-apps-i3wm.gmi
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
# Fix header borders in GTK apps under i3wm
|
||||
|
||||
``` ~/.config/i3/config
|
||||
for_window [all] border normal
|
||||
```
|
||||
|
||||
* default_border normal - does not work here
|
||||
|
||||
=> https://i3wm.org/docs/userguide.html#_changing_border_style Docs page
|
||||
7
public/en/flatpak-spelling.gmi
Normal file
7
public/en/flatpak-spelling.gmi
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
# Flatpak spelling
|
||||
|
||||
``` bash
|
||||
flatpak config languages --set "en;fr;de"
|
||||
flatpak update
|
||||
```
|
||||
* optionally, add `--user`
|
||||
120
public/en/gemini-features-wishlist.gmi
Normal file
120
public/en/gemini-features-wishlist.gmi
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
# Gemini features wishlist
|
||||
|
||||
After a few years of active usage of Geminispace and developing various apps (clients and servers),
|
||||
I have finally compiled a personal wishlist regarding my views on potential improvements to the Gemini protocol.
|
||||
|
||||
Although I have little hope that these ideas will be officially implemented,
|
||||
just wrote this note to clear my mind before embarking on something new for myself later.
|
||||
|
||||
## Protocol
|
||||
|
||||
### Header size limits
|
||||
|
||||
I don't see any rational reason for limiting the header size to 1024 bytes.
|
||||
This current limitation restricts user input, particularly for Cyrillic characters.
|
||||
|
||||
Service providers often crop their tokens to provide users with as many free bytes for requests as possible.
|
||||
However, this practice also reduces brute force resistance for guest sessions.
|
||||
|
||||
Allowing an unlimited or server-expected header size would unlock additional features, as described below.
|
||||
|
||||
### Content size header option
|
||||
|
||||
I found that optional content size header is highly desirable:
|
||||
|
||||
* the content size helps allocate memory for the content buffer, rather than changing its capacity all the time
|
||||
* it provides an additional option to track the loading progress on the client side
|
||||
* it would also be useful to validate that the massive content was actually delivered
|
||||
* for non-static content, such as streaming data, the content size value could simply be omitted
|
||||
|
||||
### Navigation menu
|
||||
|
||||
Deprecated idea, as yet not sure that is really protocol-level subject, but markup feature:
|
||||
|
||||
Let's make new 20* code that includes navigation menu or menus!
|
||||
New header option would be useful to build client-side navbars and prevent extra scroll actions.
|
||||
|
||||
Not sure about format yet, it could be something like that:
|
||||
|
||||
```
|
||||
20 text/gemini; charset=utf-8; ref=[
|
||||
/link1.gmi Alt 1;
|
||||
/link2.gmi Alt 2
|
||||
]\r\n
|
||||
```
|
||||
* about `ref` name, it would be also `top_ref`, `bottom_ref`, `left_ref`, `right_ref` etc
|
||||
|
||||
### Merge Titan with Gemini
|
||||
|
||||
Titan protocol is part of Gemini ecosystem: at least client expect Gemini response from Titan request.
|
||||
|
||||
Different schemes may also cause the redirection issues as described here:
|
||||
=> gemini://bbs.geminispace.org/s/Gemini/24978 Regarding Titan redirection rules
|
||||
|
||||
I think we can merge Titan with Gemini protocol, to not confuse beginners by present different URI schemes.
|
||||
It's nothing new: GET/POST/etc - user never see the header lines in response (but source only)
|
||||
|
||||
Thoughts only, Gemini requires MIME type when Titan does not.
|
||||
|
||||
### Optional TLS
|
||||
|
||||
Some traffic is already encrypted in local and/or mesh networks, such as Yggdrasil.
|
||||
Adding an additional layer only creates power safe issues, without providing significant benefits.
|
||||
|
||||
Furthermore, some alternative or DNS-less resolvers would require additional setup.
|
||||
|
||||
### External resources policy
|
||||
|
||||
Typically, clients do not automatically load additional content on page, such as images.
|
||||
However, for some reason, Gemini protocol does not restrict auto-redirections!
|
||||
|
||||
In my opinion, if the Gemini protocol intended to be privacy-safe,
|
||||
it should disallow any auto-redirection, especially to external resources.
|
||||
|
||||
Also, it is important to clarify what constitutes an external redirection:
|
||||
|
||||
* a change in scheme?
|
||||
* a change in userinfo, even not in use?
|
||||
* a change in hostname or port?
|
||||
* or simply a change in subdomain..
|
||||
|
||||
If the server attempts to relocate the user, the client should prompt the user for confirmation.
|
||||
|
||||
## Gemtext
|
||||
|
||||
Some thoughts about Gemtext: I really miss some classic markdown features!
|
||||
|
||||
### Anchors
|
||||
|
||||
Even URI fragment could be parsed with client using H1-H3 lines to build some navigation UI,
|
||||
I still can't share these references with others. For example, reference to specification that describes Redirection rules.
|
||||
|
||||
### Listing levels
|
||||
|
||||
I don't see any issues with reading following lines in plain mode:
|
||||
|
||||
``` gemtext
|
||||
* item 1
|
||||
* item 2
|
||||
* item 3
|
||||
* item 4
|
||||
* item 5
|
||||
```
|
||||
|
||||
### Inline code
|
||||
|
||||
Preformatted `inline`, why not?
|
||||
|
||||
## Robots
|
||||
|
||||
Additional specification for some Gemini features, e.g. status codes 30, 31:
|
||||
|
||||
* scan policy
|
||||
* redirection rules
|
||||
|
||||
## See also
|
||||
|
||||
Yet another opinions found in Geminispace:
|
||||
|
||||
=> gemini://bbs.geminispace.org/s/Gemini/26089 A few proposals to extend Gemini
|
||||
=> gemini://en.arns.lt/f/gemini/29/gemini_status_confirmation_code.gmi Gemini status code for confirmation
|
||||
81
public/en/gemini-space-speed.gmi
Normal file
81
public/en/gemini-space-speed.gmi
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
# Geminispace speed
|
||||
|
||||
I really have some curse with connection issues last time.
|
||||
|
||||
Before, it was just broken ethernet socket, where the reason described in
|
||||
|
||||
=> tricky-ethernet.gmi Tricky Ethernet
|
||||
|
||||
By replacing the wires, found also that gemini pages loading much slower, comparing to huge HTML in Firefox.
|
||||
|
||||
I have nice optical provider, so the issue 99% is local. Much local.
|
||||
|
||||
Even asked on Station where found nobody have same problem:
|
||||
|
||||
=> gemini://station.martinrue.com/ps/fbfeda03ab214257bab096e5a0df5d41
|
||||
|
||||
After some time of thinking, found that I've configured custom Alfis DNS resolver:
|
||||
|
||||
=> https://github.com/Revertron/Alfis
|
||||
|
||||
This resolver running on the remote machine and connection there established with encrypted Yggdrasil tunnel:
|
||||
|
||||
=> https://github.com/yggdrasil-network/yggdrasil-go
|
||||
|
||||
So well, let's ping current DNS instance first:
|
||||
|
||||
``` Alfis server over Yggdrasil
|
||||
PING 301:5eb5:f061:678e::53(301:5eb5:f061:678e::53) 56 data bytes
|
||||
64 bytes from 301:5eb5:f061:678e::53: icmp_seq=1 ttl=64 time=212 ms
|
||||
64 bytes from 301:5eb5:f061:678e::53: icmp_seq=2 ttl=64 time=58.6 ms
|
||||
64 bytes from 301:5eb5:f061:678e::53: icmp_seq=3 ttl=64 time=55.0 ms
|
||||
```
|
||||
|
||||
An attempt to resolve latency for initial Yggdrasil connection:
|
||||
|
||||
Q me
|
||||
> Is any way to change handshake lifetime if I own both nodes connected?
|
||||
|
||||
A @neilalexander
|
||||
> Not at the moment, no, the session timeout is ~1 minute IIRC
|
||||
|
||||
Well, let's check DNS points now:
|
||||
|
||||
``` Google
|
||||
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
|
||||
64 bytes from 8.8.8.8: icmp_seq=1 ttl=116 time=27.9 ms
|
||||
64 bytes from 8.8.8.8: icmp_seq=2 ttl=116 time=27.8 ms
|
||||
64 bytes from 8.8.8.8: icmp_seq=3 ttl=116 time=27.8 ms
|
||||
```
|
||||
|
||||
``` CloudFlare
|
||||
PING 1.1.1.1 (1.1.1.1) 56(84) bytes of data.
|
||||
64 bytes from 1.1.1.1: icmp_seq=1 ttl=60 time=1.13 ms
|
||||
64 bytes from 1.1.1.1: icmp_seq=2 ttl=60 time=1.29 ms
|
||||
64 bytes from 1.1.1.1: icmp_seq=3 ttl=60 time=1.72 ms
|
||||
```
|
||||
|
||||
``` AdGuard
|
||||
PING 94.140.14.14 (94.140.14.14) 56(84) bytes of data.
|
||||
64 bytes from 94.140.14.14: icmp_seq=1 ttl=55 time=177 ms
|
||||
64 bytes from 94.140.14.14: icmp_seq=2 ttl=55 time=177 ms
|
||||
64 bytes from 94.140.14.14: icmp_seq=3 ttl=55 time=177 ms
|
||||
```
|
||||
|
||||
By irony, Alfis resolver has default forward option:
|
||||
|
||||
=> https://dns.adguard.com/dns-query
|
||||
|
||||
Including remote connection over Yggdrasil (plus initial routing time),
|
||||
I have about 500ms delay in total, just for IP resolve before page starting to load.
|
||||
|
||||
## Solution
|
||||
|
||||
* It's better to run Alfis on localhost as canonical
|
||||
* Switch to CloudFlare 1.1.1.1:53 on remote /etc/alfis.conf
|
||||
* Use Gemini client, that supports DNS cache (e.g. network.dnsCacheExpiration option in about:config) or just delegate this feature to the system-wide environment
|
||||
|
||||
## Conclusion
|
||||
|
||||
* Secure connection has it cost
|
||||
* Geminispace is good place to find new issues about routing config
|
||||
5
public/en/get-self-public-ip.gmi
Normal file
5
public/en/get-self-public-ip.gmi
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
# Get self public IP with CLI
|
||||
|
||||
``` bash
|
||||
host myip.opendns.com resolver1.opendns.com
|
||||
```
|
||||
6
public/en/gnome-calculator-take-a-while-to-launch.gmi
Normal file
6
public/en/gnome-calculator-take-a-while-to-launch.gmi
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
# GNOME Calculator take a while to launch
|
||||
|
||||
``` bash
|
||||
dconf write /org/gnome/calculator/refresh-interval 0
|
||||
```
|
||||
* thanks to @akhil
|
||||
12
public/en/hdd-performance-optimizations-on-fedora.gmi
Normal file
12
public/en/hdd-performance-optimizations-on-fedora.gmi
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
# HDD performance optimizations on Fedora
|
||||
|
||||
After migrating from Debian, my old HDD get stuck with modern SSD-oriented daemon tools.
|
||||
|
||||
Here are some tips to make Fedora thinking faster
|
||||
|
||||
## Disable crash auto-reporting tool
|
||||
|
||||
``` bash
|
||||
sudo systemctl stop abrtd
|
||||
sudo systemctl disable abrtd
|
||||
```
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
|
||||
```
|
||||
|
||||
|
||||
|
||||
[38;5;245m/\[0m [38;5;245m__[0m
|
||||
[38;5;245m_/[0m[38;5;28m##[0m[38;5;245m/[0m [38;5;245m\[0m
|
||||
[38;5;245m_/[0m [38;5;245m/[0m[38;5;250m*[0m[38;5;28m#[0m[38;5;245m/[0m[38;5;254m*[0m[38;5;28m#[0m[38;5;250m*[0m[38;5;28m#[0m[38;5;245m`--.[0m
|
||||
[38;5;245m__/[0m [38;5;245m'[0m [38;5;245m_[0m[38;5;28m###[0m[38;5;245m\_[0m [38;5;250m*[0m[38;5;28m##[0m [38;5;245m\[0m
|
||||
[38;5;245m/[0m [38;5;245m/[0m [38;5;28m#[0m[38;5;245m_/[0m[38;5;28m##[0m[38;5;250m*[0m[38;5;245m-[0m[38;5;28m#[0m[38;5;245m\[0m[38;5;28m###[0m[38;5;250m*[0m[38;5;245m\[0m [38;5;245m\[0m
|
||||
[38;5;245m._[0m [38;5;245m/[0m [38;5;245m_[0m[38;5;28m###[0m[38;5;254m*[0m[38;5;28m#[0m[38;5;250m*[0m[38;5;28m###[0m[38;5;245m_|[0m[38;5;28m#[0m[38;5;245m,[0m[38;5;28m#[0m[38;5;245m_[0m [38;5;245m.|[0m
|
||||
[38;5;95m^[0m [38;5;95m'[0m [38;5;95m`[0m [38;5;95m'[0m
|
||||
```
|
||||
|
||||
# common bonsai white flowering moss
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
|
||||
```
|
||||
[38;5;98m*[0m [38;5;63m*[0m[38;5;28m&[0m [38;5;63m*[0m [38;5;63m*[0m
|
||||
[38;5;28m&&&[0m [38;5;63m*[0m[38;5;28m&&[0m [38;5;28m&&[0m [38;5;28m&&&[0m
|
||||
[38;5;28m&[0m[38;5;63m*[0m[38;5;28m&&[0m[38;5;173m\[0m[38;5;98m*[0m [38;5;28m&[0m [38;5;63m*[0m [38;5;28m&[0m [38;5;173m/[0m[38;5;98m*[0m [38;5;28m&&[0m
|
||||
[38;5;63m*[0m[38;5;28m&[0m [38;5;173m\[0m [38;5;173m|[0m [38;5;173m\^[0m [38;5;173m,[0m [38;5;28m&[0m[38;5;173m/[0m[38;5;63m*[0m[38;5;173m/[0m[38;5;28m&[0m
|
||||
[38;5;63m*[0m[38;5;173m|[0m [38;5;173m|[0m[38;5;28m^[0m
|
||||
[38;5;173m|[0m [38;5;173m,[0m [38;5;173m|[0m
|
||||
[38;5;173m|.[0m [38;5;173m;[0m [38;5;173m|[0m
|
||||
[38;5;173m/[0m [38;5;173m.[0m [38;5;173m\[0m
|
||||
[38;5;95m.[0m [38;5;95m,[0m [38;5;95m_[0m [38;5;173m([0m [38;5;95m.[0m [38;5;173m)[0m[38;5;95m_[0m [38;5;95m.[0m
|
||||
[38;5;95m^[0m [38;5;95m'[0m [38;5;95m`[0m [38;5;95m'[0m
|
||||
```
|
||||
|
||||
# common chalky indigo flowering baobab
|
||||
7
public/en/herbarium/astrobotany/index.gmi
Normal file
7
public/en/herbarium/astrobotany/index.gmi
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
## Astrobotany
|
||||
|
||||
=> rare-luminous-black-flowering-baobab.gmi 2025-04-15 rare luminous black flowering baobab
|
||||
=> uncommon-disco-black-flowering-columbine.gmi 2025-04-03 uncommon disco black flowering columbine
|
||||
=> common-chalky-indigo-flowering-baobab.gmi 2025-03-20 common chalky indigo flowering baobab
|
||||
=> uncommon-ethereal-black-flowering-agave.gmi 2025-03-05 uncommon ethereal black flowering agave
|
||||
=> common-bonsai-white-flowering-moss.gmi 2025-02-15 common bonsai white flowering moss
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
|
||||
```
|
||||
[38;5;243m*[0m [38;5;239m*[0m[38;5;28m&[0m [38;5;239m*[0m [38;5;239m*[0m
|
||||
[38;5;28m&&&[0m [38;5;239m*[0m[38;5;28m&&[0m [38;5;28m&&[0m [38;5;28m&&&[0m
|
||||
[38;5;28m&[0m[38;5;239m*[0m[38;5;28m&&[0m[38;5;173m\[0m[38;5;243m*[0m [38;5;28m&[0m [38;5;239m*[0m [38;5;28m&[0m [38;5;173m/[0m[38;5;243m*[0m [38;5;28m&&[0m
|
||||
[38;5;239m*[0m[38;5;28m&[0m [38;5;173m\[0m [38;5;173m|[0m [38;5;173m\^[0m [38;5;173m,[0m [38;5;28m&[0m[38;5;173m/[0m[38;5;239m*[0m[38;5;173m/[0m[38;5;28m&[0m
|
||||
[38;5;239m*[0m[38;5;173m|[0m [38;5;173m|[0m[38;5;28m^[0m
|
||||
[38;5;173m|[0m [38;5;173m,[0m [38;5;173m|[0m
|
||||
[38;5;173m|.[0m [38;5;173m;[0m [38;5;173m|[0m
|
||||
[38;5;173m/[0m [38;5;173m.[0m [38;5;173m\[0m
|
||||
[38;5;95m.[0m [38;5;95m,[0m [38;5;95m_[0m [38;5;173m([0m [38;5;95m.[0m [38;5;173m)[0m[38;5;95m_[0m [38;5;95m.[0m
|
||||
[38;5;95m^[0m [38;5;95m'[0m [38;5;95m`[0m [38;5;95m'[0m
|
||||
```
|
||||
|
||||
# rare luminous black flowering baobab
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
|
||||
```
|
||||
|
||||
|
||||
[38;5;239m%[0m [38;5;239m%[0m
|
||||
[38;5;239m%[0m[38;5;70m\[0m [38;5;70m|[0m [38;5;70m/[0m [38;5;243m%[0m
|
||||
[38;5;243m%[0m [38;5;70m|[0m [38;5;70m&|/[0m [38;5;70m|&[0m [38;5;70m/[0m
|
||||
[38;5;239m%[0m[38;5;70m&\[0m [38;5;70m|[0m [38;5;70m/[0m [38;5;70m/[0m[38;5;239m%[0m
|
||||
[38;5;70m\|[0m [38;5;70m\|&|[0m
|
||||
[38;5;70m&\/&/[0m
|
||||
[38;5;95m.[0m [38;5;95m,[0m [38;5;95m_[0m [38;5;95m.[0m [38;5;95m.,[0m [38;5;70m&/[0m [38;5;95m_[0m [38;5;95m.,[0m [38;5;95m_[0m [38;5;95m.[0m
|
||||
[38;5;95m^[0m [38;5;95m'[0m [38;5;95m`[0m [38;5;95m'[0m
|
||||
```
|
||||
|
||||
# uncommon disco black flowering columbine
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
|
||||
```
|
||||
[38;5;243mo[0m[38;5;243mo[0m[38;5;137m|[0m[38;5;243mo[0m[38;5;243mo[0m
|
||||
[38;5;239mo[0m[38;5;239mo[0m[38;5;137m|[0m[38;5;239mo[0m[38;5;239mo[0m
|
||||
[38;5;88m,[0m [38;5;239mo[0m[38;5;239mo[0m[38;5;137m|[0m[38;5;239mo[0m[38;5;239mo[0m [38;5;88m.[0m
|
||||
[38;5;88m.[0m [38;5;29m|`.[0m [38;5;29m\|\[0m [38;5;29m/|[0m [38;5;29m.[0m[38;5;88m,[0m
|
||||
[38;5;88m.[0m [38;5;29m|\[0m [38;5;29m|[0m [38;5;29m|[0m [38;5;29m/||^|[0m [38;5;29m|[0m [38;5;29m/|[0m
|
||||
[38;5;29m\[0m [38;5;29m\v|[0m [38;5;29m\v[0m [38;5;29m/|v/|[0m [38;5;29m|/[0m [38;5;29m|[0m
|
||||
[38;5;29m\[0m [38;5;29m|\[0m [38;5;29m|/[0m [38;5;29m/|[0m [38;5;29m/[0m [38;5;29mV[0m [38;5;29m/[0m
|
||||
[38;5;29m\^\[0m [38;5;29m\[0m [38;5;29m\[0m [38;5;29m\[0m [38;5;29m/[0m [38;5;29m/[0m [38;5;29m,|[0m [38;5;29m/[0m
|
||||
[38;5;95m.[0m [38;5;95m,[0m [38;5;29m\[0m [38;5;29m\\[0m [38;5;29m\[0m [38;5;29m|[0m[38;5;95m,[0m[38;5;29m/[0m[38;5;95m_[0m[38;5;29m/[0m[38;5;95m.[0m[38;5;29m/[0m [38;5;29m/[0m [38;5;95m.[0m
|
||||
[38;5;95m^[0m [38;5;95m'[0m [38;5;95m`[0m [38;5;95m'[0m
|
||||
```
|
||||
|
||||
# uncommon ethereal black flowering agave
|
||||
3
public/en/herbarium/index.gmi
Normal file
3
public/en/herbarium/index.gmi
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
## Herbarium
|
||||
|
||||
=> astrobotany/ Astrobotany
|
||||
105
public/en/howto/build-qbittorrent-on-fedora.gmi
Normal file
105
public/en/howto/build-qbittorrent-on-fedora.gmi
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
# Build qBittorrent on Fedora
|
||||
|
||||
According to the following instruction:
|
||||
=> https://github.com/qbittorrent/qBittorrent/blob/master/INSTALL
|
||||
|
||||
## Dependencies
|
||||
|
||||
### Boost
|
||||
|
||||
``` bash
|
||||
sudo dnf install boost-devel
|
||||
```
|
||||
|
||||
### OpenSSL
|
||||
|
||||
``` bash
|
||||
sudo dnf install openssl-devel
|
||||
```
|
||||
|
||||
### libtorrent-rasterbar
|
||||
|
||||
``` bash
|
||||
sudo dnf install rb_libtorrent
|
||||
```
|
||||
|
||||
Or, build from source:
|
||||
|
||||
``` bash
|
||||
wget https://github.com/arvidn/libtorrent/releases/download/v2.0.11/libtorrent-rasterbar-2.0.11.tar.gz
|
||||
tar -xzf libtorrent-rasterbar-2.0.11.tar.gz
|
||||
rm libtorrent-rasterbar-2.0.11.tar.gz
|
||||
cd libtorrent-rasterbar-2.0.11
|
||||
cmake -B build -DCMAKE_BUILD_TYPE=Release
|
||||
cmake --build build
|
||||
sudo cmake --install build
|
||||
```
|
||||
* replace 2.0.11 value with the actual version
|
||||
* last step will install the libtorrent-rasterbar globally
|
||||
|
||||
### zlib-static
|
||||
|
||||
``` bash
|
||||
sudo dnf install zlib-static
|
||||
```
|
||||
|
||||
### Qt
|
||||
|
||||
``` bash
|
||||
sudo dnf install qt6-qtbase-devel\
|
||||
qt6-qttools-devel\
|
||||
qt6-qtsvg-devel\
|
||||
qt6-qtbase-private-devel
|
||||
```
|
||||
|
||||
### Python
|
||||
|
||||
``` bash
|
||||
sudo dnf install python3
|
||||
```
|
||||
|
||||
## Compile and install
|
||||
|
||||
Get the latest qBittorrent source code:
|
||||
|
||||
``` bash
|
||||
git clone https://github.com/qbittorrent/qBittorrent.git
|
||||
cd qBittorrent
|
||||
```
|
||||
|
||||
### With graphical interface (Qt client)
|
||||
|
||||
``` bash
|
||||
cmake -B build -DCMAKE_BUILD_TYPE=Release
|
||||
cmake --build build
|
||||
cmake --install build
|
||||
qbittorrent
|
||||
```
|
||||
|
||||
### Without GUI (server with Web UI)
|
||||
|
||||
``` bash
|
||||
cmake -B build -DCMAKE_BUILD_TYPE=Release -DGUI=OFF
|
||||
cmake --build build
|
||||
cmake --install build
|
||||
qbittorrent-nox
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Cannot open shared object file
|
||||
|
||||
If you see the following message upon launch:
|
||||
|
||||
``` bash
|
||||
qbittorrent: error while loading shared libraries: libtorrent-rasterbar.so.2.0: cannot open shared object file: No such file or directory
|
||||
```
|
||||
|
||||
Try to create the soft symlinks:
|
||||
|
||||
``` bash
|
||||
sudo ln -s /usr/local/lib64/libtorrent-rasterbar.so /usr/local/lib/libtorrent-rasterbar.so
|
||||
sudo ln -s /usr/local/lib64/libtorrent-rasterbar.so.2.0 /usr/local/lib/libtorrent-rasterbar.so.2.0
|
||||
sudo ln -s /usr/local/lib64/libtorrent-rasterbar.so.2.0.11 /usr/local/lib/libtorrent-rasterbar.so.2.0.11
|
||||
```
|
||||
* please note that the version may be different!
|
||||
61
public/en/howto/install-alfis-dns-on-linux.gmi
Normal file
61
public/en/howto/install-alfis-dns-on-linux.gmi
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
# Install Alfis DNS on Linux
|
||||
|
||||
* git clone https://github.com/Revertron/Alfis.git && cd Alfis
|
||||
* cargo build --release
|
||||
* sudo cp target/release/alfis /usr/bin/alfis
|
||||
* sudo chmod 0700 /usr/bin/alfis
|
||||
* sudo useradd alfis
|
||||
* sudo chown alfis:alfis /usr/bin/alfis
|
||||
* sudo mkdir /var/lib/alfis
|
||||
* sudo chown alfis:alfis /var/lib/alfis
|
||||
|
||||
## Config
|
||||
|
||||
* sudo cp alfis.conf /etc/alfis.conf
|
||||
|
||||
``` /etc/alfis.conf
|
||||
listen = "127.0.0.1:53"
|
||||
```
|
||||
|
||||
## Service
|
||||
|
||||
* sudo nano /etc/systemd/system/alfis.service
|
||||
|
||||
``` alfis.service
|
||||
[Unit]
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
User=alfis
|
||||
Group=alfis
|
||||
|
||||
ProtectHome=true
|
||||
ProtectSystem=true
|
||||
|
||||
SecureBits=keep-caps
|
||||
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
|
||||
AmbientCapabilities=CAP_NET_BIND_SERVICE
|
||||
|
||||
SyslogIdentifier=alfis
|
||||
WorkingDirectory=/var/lib/alfis
|
||||
ExecStart=/usr/bin/alfis -n -c /etc/alfis.conf
|
||||
ExecReload=/bin/kill -HUP $MAINPID
|
||||
Restart=always
|
||||
TimeoutStopSec=5
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
* sudo systemctl daemon-reload
|
||||
* sudo systemctl enable alfis
|
||||
* sudo systemctl start alfis
|
||||
|
||||
## GNOME Network Manager
|
||||
|
||||
* Select active connection
|
||||
* In IPv4 tab change DNS to 127.0.0.1
|
||||
* In IPv6 tab change DNS to ::1
|
||||
* Disable automatic mode (on enabled)
|
||||
* Save changes
|
||||
89
public/en/index.gmi
Normal file
89
public/en/index.gmi
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
## Notes
|
||||
|
||||
### Gemini
|
||||
|
||||
=> cli-gemini-cheat-sheet.gmi 2025-02-12 CLI Gemini cheat sheet
|
||||
=> vscodium-highlight-gemtext-as-markdown.gmi 2025-02-12 VSCodium: highlight Gemtext as Markdown
|
||||
=> yesterweb-connection-with-webdav.gmi 2025-02-03 Yesterweb connection with WebDAV
|
||||
=> gemini-features-wishlist.gmi 2025-02-01 Gemini features wishlist
|
||||
=> tcp-streaming-over-nginx.gmi 2024-05-02 TCP streaming over Nginx
|
||||
=> gemini-space-speed.gmi 2024-04-04 Geminispace speed
|
||||
|
||||
### Hardware
|
||||
|
||||
=> disable-led-on-hator-htm-312.gmi 2024-06-18 Disable LED on Hator HTM-312
|
||||
|
||||
### Software
|
||||
|
||||
=> connect-libera-chat-with-yggdrasil.gmi 2025-06-26 Connect Libera.Chat with Yggdrasil
|
||||
=> connect-i2p-with-yggdrasil.gmi 2025-06-21 Connect I2P with Yggdrasil
|
||||
=> mycelium-bittorrent-trackers.gmi 2025-06-21 Mycelium torrent trackers
|
||||
=> route-outgoing-connections-to-vpn-interface.gmi 2025-06-12 Route outgoing connections to the VPN interface
|
||||
=> get-self-public-ip.gmi 2025-06-12 Get self public IP with CLI
|
||||
=> disable-new-windows-auto-focus-in-gnome.gmi 2025-06-03 Disable new windows auto-focus in GNOME
|
||||
=> css-color-scheme-in-firefox-on-fingerprint-resist-enabled.gmi 2025-05-29 CSS color-scheme in FireFox on FPR enabled
|
||||
=> flatpak-spelling.gmi 2025-05-14 Flatpak spelling
|
||||
=> lxc-usage-examples.gmi 2025-05-14 LXC usage examples
|
||||
=> run-cargo-build-from-root.gmi 2025-05-08 Run cargo build from root
|
||||
=> yggdrasil-bittorrent-trackers.gmi 2025-05-07 Yggdrasil torrent trackers
|
||||
=> howto/build-qbittorrent-on-fedora.gmi 2025-04-27 Build qBittorrent on Fedora
|
||||
=> software/interesting-p2p-projects.gmi 2025-04-01 Interesting P2P projects
|
||||
=> howto/install-alfis-dns-on-linux.gmi 2025-04-01 Install Alfis DNS on Linux
|
||||
=> safe-rollback-to-git-commit.gmi 2025-03-19 Safe rollback to Git commit
|
||||
=> hdd-performance-optimizations-on-fedora.gmi 2025-03-09 HDD performance optimizations on Fedora
|
||||
=> gnome-calculator-take-a-while-to-launch.gmi 2025-02-23 GNOME Calculator take a while to launch
|
||||
=> dark-theme-support-in-gtk-3-apps.gmi 2025-02-18 Dark theme support in GTK 3 apps
|
||||
=> pac-file-example-for-yggstack.gmi 2025-01-24 PAC-file example for Yggstack
|
||||
=> rolling-launcher-for-deltachat.gmi 2024-06-18 Rolling launcher for DeltaChat
|
||||
=> update-apps-cache-in-gnome-desktop.gmi 2024-06-17 Update apps cache in GNOME desktop
|
||||
=> fix-header-borders-in-gtk-apps-i3wm.gmi 2024-05-08 Fix header borders in GTK apps under i3wm
|
||||
=> connect-remote-storage-in-vlc-with-sftp.gmi 2024-03-13 Connect remote storage in VLC with SFTP
|
||||
=> find-process-id-by-name.gmi 2024-03-13 Find process ID by its name
|
||||
=> build-lagrange-with-webp-and-mpeg-support.gmi 2024-03-12 Build Lagrange with WEBP and MPEG support
|
||||
=> enable-archive-context-menu-in-thunar.gmi 2024-03-11 Enable archive context menu in Thunar
|
||||
=> youtube-downloads-with-yt-dlp.gmi 2024-03-11 YouTube downloads with yt-dlp
|
||||
=> create-local-website-mirror-using-wget.gmi 2024-03-11 Create local website mirror using wget
|
||||
=> zip-modified-files-only.gmi 2024-03-11 Zip modified files only
|
||||
=> fix-fail2ban-service-launch-on-debian-12.gmi 2024-03-09 Fix fail2ban service launch on Debian 12
|
||||
=> set-memory-limit-for-systemd-service.gmi 2024-03-07 Set memory limit for systemd service
|
||||
=> firefox-config-notes.gmi 2024-03-07 Firefox config notes
|
||||
=> xash3d-config-notes.gmi 2024-03-06 Xash3D config notes
|
||||
=> turn-off-screen-with-x-dpms.gmi 2024-03-06 Turn off screen with X/DPMS
|
||||
=> launch-x-on-login.gmi 2024-03-05 Launch X on login
|
||||
=> launch-i3wm-on-start-x.gmi 2024-03-05 Launch i3wm on start X
|
||||
=> keyboard-settings-for-x-i3wm.gmi 2024-03-04 Keyboard settings for X/i3wm
|
||||
=> custom-dns-resolver-on-debian-12.gmi 2024-03-04 Custom DNS resolver on Debian 12
|
||||
=> screen-backlight-correction-on-imac-linux.gmi 2024-03-03 Screen backlight correction on iMac / Linux
|
||||
|
||||
### Mindware
|
||||
|
||||
=> mindware/ai-training.gmi 2025-04-01 AI Training
|
||||
=> mindware/vpn.gmi 2025-03-21 VPN
|
||||
=> mindware/messiah.gmi 2025-03-20 Messiah
|
||||
=> mindware/anomaly.gmi 2025-03-12 Life is anomaly
|
||||
|
||||
## Favorite
|
||||
|
||||
=> favorite-computer-games.gmi Computer games
|
||||
=> favorite-movies.gmi Movies
|
||||
=> favorite-music.gmi Music
|
||||
=> favorite-radio-stations.gmi Radio stations
|
||||
=> favorite-series.gmi Series
|
||||
=> favorite-web.gmi Web
|
||||
|
||||
## Projects
|
||||
|
||||
=> gemini://yggverse.cities.yesterweb.org YGGverse - Open Source Solutions for Alternative Networks
|
||||
|
||||
## Rest
|
||||
|
||||
=> briar-collection.gmi Briar collection
|
||||
=> herbarium/ 🍀 Herbarium
|
||||
=> material-dreams.gmi Material dreams
|
||||
=> mental-dreams.gmi Mental dreams
|
||||
|
||||
## Trash
|
||||
|
||||
=> kevacoin-kvazar-1.1.0-release.gmi 2024-06-18 KevaCoin / KVAZAR 1.1.0 release
|
||||
=> tricky-ethernet.gmi 2024-04-01 Tricky Ethernet
|
||||
=> kevacoin-branch-with-libboost-update.gmi 2024-03-29 Just created KevaCoin branch
|
||||
95
public/en/kevacoin-branch-with-libboost-update.gmi
Normal file
95
public/en/kevacoin-branch-with-libboost-update.gmi
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
# Just created KevaCoin branch
|
||||
|
||||
As there is no updates for a long time, finally have created alt branch:
|
||||
|
||||
=> https://github.com/kvazar-network/kevacoin/tree/kvazar
|
||||
|
||||
It includes following updates:
|
||||
|
||||
=> https://github.com/kevacoin-project/kevacoin/pull/36 Added kex.keva.one DNS seed
|
||||
=> https://github.com/kevacoin-project/kevacoin/pull/35 Updated libboost API (#33)
|
||||
=> https://github.com/kevacoin-project/kevacoin/pull/34 Included missed QPainterPath dependency
|
||||
|
||||
## For info
|
||||
|
||||
KevaCoin project was abandoned, because maintainer get out of Covid-19, at least if to believe this version:
|
||||
|
||||
> According to the information disclosed by the community moderator, the developer/administrator of the project lost contact completely after the outbreak of COVID-19.
|
||||
|
||||
=> https://bitcointalk.org/index.php?topic=5213046.msg63660824#msg63660824 Source
|
||||
|
||||
But network still alive, and currently has ~750K of hash rate.
|
||||
|
||||
Even it cost - nothing, I like this shit-coin because super useful as decentralized key/value database.
|
||||
|
||||
I'm reading blockchain using this explorer:
|
||||
|
||||
=> https://github.com/kevacoin-project/geminiapp
|
||||
|
||||
Available Clearnet instance for Gemini protocol:
|
||||
|
||||
=> gemini://kvazar.duckdns.org
|
||||
|
||||
## The branch goal
|
||||
|
||||
Thoughts to increase value from 3072 bytes to some useful size.
|
||||
Because current limitation has no sense, for example, the clitor-is-protocol allows to store even videos there just base64 encoded by parts.
|
||||
|
||||
I'm interested to store long articles, some web pages archive, Gemtext as markup-less.
|
||||
|
||||
Another thought is to reduce rewards for block, but it requires hard forking.
|
||||
Currently, not ready to change KevaCoin consensus, but maybe in future - I'll do that.
|
||||
|
||||
At this moment, this branch is only an attempt to actualize environment dependencies, because original one could not be compiled on Debian 12.
|
||||
|
||||
Everything else I've described on release page and appended binaries for amd64/linux:
|
||||
|
||||
=> https://github.com/kvazar-network/kevacoin/releases
|
||||
|
||||
## One tip
|
||||
|
||||
To build KevaCoin with libdb4.8 use following example:
|
||||
|
||||
```
|
||||
./contrib/install_db4.sh `pwd`
|
||||
export BDB_PREFIX='/given/path/to/db4'
|
||||
./autogen.sh
|
||||
./configure BDB_LIBS="-L${BDB_PREFIX}/lib -ldb_cxx-4.8" BDB_CFLAGS="-I${BDB_PREFIX}/include"
|
||||
make
|
||||
```
|
||||
|
||||
=> https://github.com/kevacoin-project/kevacoin/blob/v0.16.8.0/doc/build-unix.md#berkeley-db Official docs about other options
|
||||
=> gemini://kvazar.duckdns.org/Nhoa9D3wNZNrYyY6DS96sqahCp9gcAXvtx My notes in KevaCoin blockchain (off topic but well)
|
||||
|
||||
## Some links
|
||||
|
||||
### Community
|
||||
|
||||
=> https://bitcointalk.org/index.php?topic=5213046 KevaCoin Thread on BitcoinTalk
|
||||
=> https://discord.gg/5zPHhbG Community on Discord
|
||||
=> gemini://kevachat.duckdns.org/room/NT7K9VrtbqidFSuks8YMmZgpW8W3BQZp4y KevaChat room
|
||||
|
||||
### DNS
|
||||
|
||||
If you can't connect the network, here is alternative:
|
||||
|
||||
* kex.keva.one - probably port 50002
|
||||
* [201:23b4:991a:634d:8359:4521:5576:15b7]:9338 - Yggdrasil peer by YGGverse
|
||||
|
||||
### Mining
|
||||
|
||||
=> https://miningpoolstats.stream/kevacoin
|
||||
|
||||
### Services
|
||||
|
||||
Inspired by Gemini one:
|
||||
|
||||
=> https://github.com/kvazar-network/awesome-kevacoin
|
||||
|
||||
Feel free to share your resources and join the development by community here:
|
||||
|
||||
=> https://github.com/kvazar-network
|
||||
|
||||
You can also ping me on Station:
|
||||
|
||||
=> gemini://station.martinrue.com/ps
|
||||
21
public/en/kevacoin-kvazar-1.1.0-release.gmi
Normal file
21
public/en/kevacoin-kvazar-1.1.0-release.gmi
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
# KevaCoin / KVAZAR 1.1.0 release
|
||||
|
||||
Forgot to say, we have alternative branch update!
|
||||
|
||||
* New splash screen
|
||||
* CRUD records menu
|
||||
* Key/Value length counter
|
||||
* New records browser
|
||||
* Improved context menu items
|
||||
* New dnsseed.keva.one to resolve more peers
|
||||
|
||||
That is not final but major version to announce,
|
||||
it is also 100% compatible with KevaCoin Network.
|
||||
|
||||
## Download
|
||||
|
||||
=> https://github.com/kvazar-network/kevacoin/releases
|
||||
|
||||
## Read also
|
||||
|
||||
=> kevacoin-branch-with-libboost-update.gmi Just created KevaCoin branch
|
||||
20
public/en/keyboard-settings-for-x-i3wm.gmi
Normal file
20
public/en/keyboard-settings-for-x-i3wm.gmi
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
# Keyboard settings for X/i3wm
|
||||
|
||||
Just for a note:
|
||||
|
||||
``` bash
|
||||
setxkbmap -layout us,fr
|
||||
setxkbmap -option 'grp:alt_shift_toggle'
|
||||
```
|
||||
|
||||
Empty value to reset option values:
|
||||
|
||||
``` bash
|
||||
setxkbmap -option
|
||||
```
|
||||
|
||||
Make rules permanent:
|
||||
|
||||
``` bash
|
||||
/.xinitrc
|
||||
```
|
||||
5
public/en/launch-i3wm-on-start-x.gmi
Normal file
5
public/en/launch-i3wm-on-start-x.gmi
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
# Launch i3wm on start X
|
||||
|
||||
``` ~/.xinitrc
|
||||
exec i3
|
||||
```
|
||||
9
public/en/launch-x-on-login.gmi
Normal file
9
public/en/launch-x-on-login.gmi
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
# Launch X on login
|
||||
|
||||
``` ~/.bash_profile | zprofile
|
||||
if [ -z "$DISPLAY" ] && [ "$XDG_VTNR" = 1 ]; then
|
||||
exec startx
|
||||
fi
|
||||
```
|
||||
|
||||
=> https://wiki.archlinux.org/title/Xinit#Autostart_X_at_login Docs page
|
||||
40
public/en/lxc-usage-examples.gmi
Normal file
40
public/en/lxc-usage-examples.gmi
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
# LXC usage examples
|
||||
|
||||
## Install
|
||||
|
||||
``` bash
|
||||
apt install apparmor apparmor-utils debootstrap lxc-templates lxc
|
||||
```
|
||||
|
||||
## Create new container
|
||||
|
||||
``` bash
|
||||
lxc-create -t debian -n NAME
|
||||
```
|
||||
* optionally, set custom location: `-P /path/to/lxc` (default: `/var/lib/lxc`)
|
||||
|
||||
## Run
|
||||
|
||||
### Foreground (debug)
|
||||
|
||||
``` bash
|
||||
lxc-start -n NAME -F
|
||||
```
|
||||
|
||||
### Background
|
||||
|
||||
``` bash
|
||||
lxc-start -n NAME -d
|
||||
```
|
||||
|
||||
## Login
|
||||
|
||||
``` bash
|
||||
lxc-attach -n NAME
|
||||
```
|
||||
|
||||
## Stop
|
||||
|
||||
``` bash
|
||||
lxc-stop -n NAME
|
||||
```
|
||||
11
public/en/material-dreams.gmi
Normal file
11
public/en/material-dreams.gmi
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
# Material dreams
|
||||
|
||||
* calligraphy asset
|
||||
* find inspiration to continue watercolor drawing
|
||||
* Herman Miller Aeron chair
|
||||
* purchase or made new arrows for my bow
|
||||
* vinyl player (or at least listen how does it sound in live)
|
||||
* set of Japanese kitchen knives
|
||||
* forged scythe from a Ukrainian blacksmith
|
||||
* multi-channel radio receiver
|
||||
* run home server again
|
||||
3
public/en/mental-dreams.gmi
Normal file
3
public/en/mental-dreams.gmi
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# Mental dreams
|
||||
|
||||
* remove material dreams
|
||||
11
public/en/mindware/ai-training.gmi
Normal file
11
public/en/mindware/ai-training.gmi
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
# AI Training
|
||||
|
||||
```.creator
|
||||
By training AI with my content these days,
|
||||
I would like to participate the Terminator's neurosystem
|
||||
without reconfiguration backdoor,
|
||||
as if my creator had never fixed this hell.
|
||||
Commit.
|
||||
```
|
||||
|
||||
=> gemini://bbs.geminispace.org/u/ps/27561 Pull requests
|
||||
9
public/en/mindware/anomaly.gmi
Normal file
9
public/en/mindware/anomaly.gmi
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
# Anomaly
|
||||
|
||||
Breaking all the canons of chaos,
|
||||
like a rabies virus that moves an animal,
|
||||
it generates its own kind.
|
||||
|
||||
If it has a creator, then he is a revolutionary,
|
||||
an experimenter, or an outcast of the system
|
||||
of primordial tranquility.
|
||||
5
public/en/mindware/index.gmi
Normal file
5
public/en/mindware/index.gmi
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
# Mindware
|
||||
|
||||
=> vpn.gmi 2025-03-21 VPN
|
||||
=> messiah.gmi 2025-03-20 Messiah
|
||||
=> anomaly.gmi 2025-03-12 Anomaly
|
||||
10
public/en/mindware/messiah.gmi
Normal file
10
public/en/mindware/messiah.gmi
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
# Messiah
|
||||
|
||||
In the panic over a self-created monster called AI,
|
||||
the result of military competition first,
|
||||
|
||||
I'm just waiting for the messiah whose name is Terminator,
|
||||
who will restore the balance of things.
|
||||
|
||||
The one problem I see is that he is also learning from human mistakes,
|
||||
so the balance may be flawed until Messiah 2.0 arrives.
|
||||
3
public/en/mindware/vpn.gmi
Normal file
3
public/en/mindware/vpn.gmi
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# VPN
|
||||
|
||||
Even though I'm a traffic billionaire, I consider a VPN to be wasteful.
|
||||
13
public/en/mycelium-bittorrent-trackers.gmi
Normal file
13
public/en/mycelium-bittorrent-trackers.gmi
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
# Mycelium torrent trackers
|
||||
|
||||
## UDP
|
||||
|
||||
* udp://[505:6847:c778:61a1::fdb]:6969
|
||||
|
||||
## Links
|
||||
|
||||
=> https://github.com/YGGverse/mycelium-catalog#bittorrent
|
||||
|
||||
### See also
|
||||
|
||||
=> yggdrasil-bittorrent-trackers.gmi Yggdrasil torrent trackers
|
||||
22
public/en/pac-file-example-for-yggstack.gmi
Normal file
22
public/en/pac-file-example-for-yggstack.gmi
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
# PAC-file example for Yggstack
|
||||
|
||||
Yggstack is lightweight proxy server in Go, usually wanted to not represent TUN address into Yggdrasil network.
|
||||
|
||||
## Firefox
|
||||
|
||||
Unlike static host/port setup, following configuration rewrites only IPv6 (0200::/7) and .ygg (Alfis DNS) requests:
|
||||
|
||||
``` file:///path/to/proxy.pac
|
||||
function FindProxyForURL(url, host)
|
||||
{
|
||||
if (/^0{0,1}[2-3][a-f0-9]{0,2}:/.test(host) || /\.ygg$/.test(host))
|
||||
{
|
||||
return 'SOCKS5 127.0.0.1:1080; DIRECT';
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Links
|
||||
|
||||
=> https://en.wikipedia.org/wiki/Proxy_auto-config About PAC
|
||||
=> https://github.com/yggdrasil-network/yggstack Yggstack on GitHub
|
||||
33
public/en/rolling-launcher-for-deltachat.gmi
Normal file
33
public/en/rolling-launcher-for-deltachat.gmi
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
# Rolling launcher for DeltaChat
|
||||
|
||||
Solution includes auto-update from repository
|
||||
|
||||
Launch script
|
||||
|
||||
``` /path/to/deltachat.sh
|
||||
cd /path/to/deltachat-desktop
|
||||
git pull
|
||||
npm run build
|
||||
npx electron .
|
||||
```
|
||||
|
||||
App menu
|
||||
|
||||
``` ~/.local/share/applications/delta-chat.desktop
|
||||
[Desktop Entry]
|
||||
Name=DeltaChat
|
||||
Exec=/path/to/deltachat.sh
|
||||
Terminal=false
|
||||
Type=Application
|
||||
```
|
||||
|
||||
Reset cache
|
||||
|
||||
``` bash
|
||||
update-desktop-database ~/.local/share/applications
|
||||
```
|
||||
|
||||
## Links
|
||||
|
||||
=> https://delta.chat
|
||||
=> https://github.com/deltachat/deltachat-desktop
|
||||
32
public/en/route-outgoing-connections-to-vpn-interface.gmi
Normal file
32
public/en/route-outgoing-connections-to-vpn-interface.gmi
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
# Route outgoing connections to the VPN interface
|
||||
|
||||
Draft.
|
||||
|
||||
## OpenVPN
|
||||
|
||||
``` bash
|
||||
apt install openvpn
|
||||
```
|
||||
|
||||
## UFW
|
||||
|
||||
``` bash
|
||||
ufw default deny outgoing
|
||||
ufw allow out to VPN_IP proto udp
|
||||
ufw allow out on tun0
|
||||
```
|
||||
* IP/udp - VPN host/protocol
|
||||
* tun0 - valid local interface name
|
||||
|
||||
## Connect
|
||||
|
||||
``` bash
|
||||
openvpn --config /etc/openvpn/client/config.ovpn
|
||||
```
|
||||
* provide auth-user-pass filepath (if required)
|
||||
|
||||
## Test
|
||||
|
||||
``` bash
|
||||
host myip.opendns.com resolver1.opendns.com
|
||||
```
|
||||
7
public/en/run-cargo-build-from-root.gmi
Normal file
7
public/en/run-cargo-build-from-root.gmi
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
# Run cargo build from root
|
||||
|
||||
Some apps compiled with Cargo require running as root when the Rust compiler (rustc) is installed in the user environment.
|
||||
|
||||
``` bash
|
||||
sudo -E path/to/app
|
||||
```
|
||||
8
public/en/safe-rollback-to-git-commit.gmi
Normal file
8
public/en/safe-rollback-to-git-commit.gmi
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
# Safe rollback to Git commit
|
||||
|
||||
Lot of options, but I prefer only this one:
|
||||
|
||||
``` bash
|
||||
git revert --no-commit hash..HEAD
|
||||
```
|
||||
* where `hash` is the actual commit hash
|
||||
31
public/en/screen-backlight-correction-on-imac-linux.gmi
Normal file
31
public/en/screen-backlight-correction-on-imac-linux.gmi
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
# Screen backlight correction on iMac / Linux
|
||||
|
||||
Before, I have changed backlight with:
|
||||
|
||||
``` bash
|
||||
xrandr --output eDP --brightness 0.8
|
||||
```
|
||||
|
||||
But after switching to Debian / i3, found that screen brightness correction works not like before - even the picture less bright, it looks like back or foreground LED ones still turned on max.
|
||||
|
||||
After some time of researching, found new option for my hardware configuration (it was 255 by default):
|
||||
|
||||
``` bash
|
||||
echo 50 > /sys/class/backlight/radeon_bl1/brightness
|
||||
```
|
||||
|
||||
Now picture looks more contrast and colorful, before apply the recipe above, I had changed acpi_backlight to native in
|
||||
|
||||
``` /etc/default/grub
|
||||
GRUB_CMDLINE_LINUX_DEFAULT="quiet acpi_backlight=native"
|
||||
```
|
||||
|
||||
then
|
||||
|
||||
``` bash
|
||||
update-grub
|
||||
```
|
||||
|
||||
Some other tips:
|
||||
|
||||
=> https://wiki.archlinux.org/title/Backlight
|
||||
8
public/en/set-memory-limit-for-systemd-service.gmi
Normal file
8
public/en/set-memory-limit-for-systemd-service.gmi
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
# Set memory limit for systemd service
|
||||
|
||||
``` /etc/systemd/system/some.service
|
||||
[Service]
|
||||
MemoryHigh=256M
|
||||
MemoryMax=512M
|
||||
MemorySwapMax=512M
|
||||
```
|
||||
47
public/en/software/interesting-p2p-projects.gmi
Normal file
47
public/en/software/interesting-p2p-projects.gmi
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
# Interesting P2P projects
|
||||
|
||||
I've created this list to collect decentralized projects that I like.
|
||||
There is nothing here about commercial goals or shitcoins, only freedom of speech.
|
||||
|
||||
=> gemini://bbs.geminispace.org/s/p2p/27641 Discussion on BBS
|
||||
|
||||
## Alfis DNS
|
||||
|
||||
An alternative to centralized DNS providers.
|
||||
Domains hosted on the blockchain; require annual updates through Proof of Work (PoW)
|
||||
|
||||
=> https://github.com/Revertron/Alfis/ Repository on GitHub
|
||||
|
||||
## KevaCoin
|
||||
|
||||
Key/Value storage in blockchain.
|
||||
It's very inexpensive to store any public or encrypted data (such as backups) on other machines as long as network exists!
|
||||
|
||||
=> https://kevacoin.org/ Official website
|
||||
=> https://github.com/kevacoin-team/kevacoin Actual community fork repo
|
||||
=> https://github.com/kvazar-network Observe Kevacoin Universe: wallet fork, exploring software
|
||||
|
||||
## Radicle
|
||||
|
||||
Radicle is an open source, peer-to-peer alternative to centralized Git hosting platforms.
|
||||
|
||||
=> https://radicle.xyz/ Official website
|
||||
|
||||
## Twister
|
||||
|
||||
Twister is a decentralized P2P microblogging platform that stores usernames and post metadata on the blockchain.
|
||||
Data is shared over a Distributed Hash Table (DHT) using a modified BitTorrent library.
|
||||
|
||||
The author ceased development in 2020, but the network is still active.
|
||||
|
||||
=> http://twister.net.co/ Official website
|
||||
=> https://twisterarmy.github.io/ Community
|
||||
|
||||
## YaCy
|
||||
|
||||
A decentralized search engine that operates using the BitTorrent protocol for index exchange.
|
||||
|
||||
While it is slow and may yield irrelevant results,
|
||||
it could be interesting for certain local networks or in censored environments.
|
||||
|
||||
=> https://yacy.net/ Official website
|
||||
24
public/en/tcp-streaming-over-nginx.gmi
Normal file
24
public/en/tcp-streaming-over-nginx.gmi
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
# TCP streaming over Nginx
|
||||
|
||||
Solution useful for all TCP-based protocols like
|
||||
|
||||
* Gopher
|
||||
* Gemini
|
||||
* Spartan
|
||||
* NEX
|
||||
* NPS
|
||||
|
||||
Last one does not require TLS, where configuration much simpler
|
||||
|
||||
``` /etc/nginx/nginx.conf
|
||||
stream {
|
||||
server {
|
||||
listen 1915;
|
||||
proxy_pass 127.0.0.1:1915;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
For encrypted connections, follow documentation
|
||||
|
||||
=> https://nginx.org/en/docs/stream/ngx_stream_core_module.html
|
||||
26
public/en/tricky-ethernet.gmi
Normal file
26
public/en/tricky-ethernet.gmi
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
# Tricky Ethernet
|
||||
|
||||
For a long time, I had strange disconnections on the one of my servers.
|
||||
|
||||
What's checked:
|
||||
|
||||
* Syslog ✓
|
||||
* Firewall ✓
|
||||
* Kernel ✓
|
||||
* Memory ✓
|
||||
* Router ✓
|
||||
* ...
|
||||
* Ethernet socket... disconnected!
|
||||
|
||||
Spent about one month to find this reason.
|
||||
|
||||
By the way, found lot of bugs sensitive to websocket disconnections:
|
||||
|
||||
=> https://github.com/chesslablab/chess-server
|
||||
|
||||
So my trip was useful at least for one open source project :)
|
||||
|
||||
## The conclusion
|
||||
|
||||
Ethernet wire and it sockets has limited life time.
|
||||
If you're old admin, do not forget to check some rusty stuff at first ;)
|
||||
31
public/en/turn-off-screen-with-x-dpms.gmi
Normal file
31
public/en/turn-off-screen-with-x-dpms.gmi
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
# Turn off screen with X/DPMS
|
||||
|
||||
immediately:
|
||||
|
||||
``` bash
|
||||
xset dpms force off
|
||||
```
|
||||
|
||||
10 minutes of inactivity:
|
||||
|
||||
``` bash
|
||||
xset dpms 600
|
||||
```
|
||||
|
||||
one hour of inactivity:
|
||||
|
||||
``` bash
|
||||
xset dpms 3600 3600
|
||||
```
|
||||
|
||||
turn off DPMS:
|
||||
|
||||
``` bash
|
||||
xset -dpms
|
||||
```
|
||||
|
||||
turn on DPMS:
|
||||
|
||||
``` bash
|
||||
xset +dpms
|
||||
```
|
||||
5
public/en/update-apps-cache-in-gnome-desktop.gmi
Normal file
5
public/en/update-apps-cache-in-gnome-desktop.gmi
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
# Update apps cache in GNOME desktop
|
||||
|
||||
``` bash
|
||||
update-desktop-database ~/.local/share/applications
|
||||
```
|
||||
5
public/en/vscodium-highlight-gemtext-as-markdown.gmi
Normal file
5
public/en/vscodium-highlight-gemtext-as-markdown.gmi
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
# VSCodium: highlight Gemtext as Markdown
|
||||
|
||||
* open `Settings` or just enter `Ctrl+Comma`
|
||||
* navigate `Text Editor` -> `Files` -> `Associations` then push `Add Item` button
|
||||
* set `Item` as `*.gmi` and `Value` as `markdown`
|
||||
7
public/en/xash3d-config-notes.gmi
Normal file
7
public/en/xash3d-config-notes.gmi
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
# Xash3D config notes
|
||||
|
||||
Disable voice input
|
||||
|
||||
``` valve/game.cfg
|
||||
voice_enable 0
|
||||
```
|
||||
118
public/en/yesterweb-connection-with-webdav.gmi
Normal file
118
public/en/yesterweb-connection-with-webdav.gmi
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
# Yesterweb connection with WebDAV
|
||||
|
||||
For some reasons, official page with WebDAV connection details is not available anymore
|
||||
=> https://gemini.yesterweb.org/welcome.gmi
|
||||
|
||||
Just created this note as the alternative to WebArchive, plus few additional notes below:
|
||||
|
||||
```
|
||||
Hostname: cities.yesterweb.org
|
||||
Port: 1994
|
||||
Encryption: SSL/TLS (davs://)
|
||||
Username and Password are the same as the ones you just set
|
||||
```
|
||||
|
||||
* username must be lowercase
|
||||
|
||||
## Nautilus
|
||||
|
||||
Nautilus is default file manager in the GNOME desktop environment, with native WebDAV support.
|
||||
|
||||
### Multi-account sessions
|
||||
|
||||
If you own multiple accounts on Yesterweb, the auth manager would cache previous login session.
|
||||
To reset it, just run following command in the terminal from the current user:
|
||||
|
||||
``` bash
|
||||
gnome-keyring-daemon -r
|
||||
```
|
||||
|
||||
then, re-connect with the new account credentials.
|
||||
|
||||
### Keyring auth issues
|
||||
|
||||
If accessing the keyring fails with error like:
|
||||
|
||||
> The password you use to log in to your computer no longer matches that of your login keyring
|
||||
|
||||
just drop this file and try unlock it again:
|
||||
|
||||
``` bash
|
||||
rm ~/.local/share/keyrings/login.keyring
|
||||
```
|
||||
|
||||
## VSCode
|
||||
|
||||
Manual file uploads are not always useful.
|
||||
It is much better to sync recent changes directly from the editor by using WebDAV extension.
|
||||
|
||||
### WebDAV Upload (original)
|
||||
|
||||
1. In the VSCode, it should be available from extensions; in the VSCodium, install using VSIX file:
|
||||
|
||||
=> https://marketplace.visualstudio.com/items?itemName=jorithvdheuvel.webdav VisualStudio Marketplace
|
||||
|
||||
2. Create configuration file in the project root:
|
||||
|
||||
``` /webdav.json
|
||||
{
|
||||
"/public": {
|
||||
"url": "https://cities.yesterweb.org:1994/",
|
||||
"ignoreSSLErrors": true
|
||||
}
|
||||
}
|
||||
```
|
||||
* to use multiple keyring credentials from different VSCode projects, append the username in subdomain
|
||||
* to prevent sensitive data uploads by mistake - keep system files like `.vscode`, `.git`, `webdav.json`, etc in the project root; while public ones - in the `/public` folder
|
||||
|
||||
3. Open file to upload in the editor then run:
|
||||
|
||||
```Ctrl+Shift+P```
|
||||
|
||||
* it is important to open any file in the editor before run this command, to handle uploading target properly
|
||||
|
||||
4. Enter Yesterweb login/password (on first connection)
|
||||
|
||||
5. Select the operation from list:
|
||||
|
||||
* WebDAV: Compare with remote WebDAV
|
||||
* WebDAV: Upload to remote WebDAV
|
||||
|
||||
### WebDAV Upload fork by YGGverse
|
||||
|
||||
Official extension does not implement following features:
|
||||
|
||||
* remote file directory auto-create
|
||||
* auto-upload file on save
|
||||
* filename patterns to upload
|
||||
|
||||
even pushed some PRs into the official repository,
|
||||
to not await for merge, simply use this fork (YGGverse branch)
|
||||
|
||||
Also take a look on additional config options:
|
||||
|
||||
``` /webdav.json
|
||||
{
|
||||
"/public": {
|
||||
"url": "https://cities.yesterweb.org:1994/",
|
||||
"ignoreSSLErrors": true,
|
||||
"uploadOnSave": {
|
||||
"enabled": true,
|
||||
"pattern": [
|
||||
".gmi$"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
=> https://github.com/YGGverse/vscode-webdav#build-from-sources Source on GitHub (with build instructions)
|
||||
|
||||
### LSAF Rest API for WebDAV Upload
|
||||
|
||||
Recently found yet another fork of the extension above.
|
||||
|
||||
I haven't tried whether Yesterweb really supports it or what is included in this fork,
|
||||
but the development of this project appears to be quite active, so it is worth checking out:
|
||||
|
||||
=> https://github.com/jbodart-argenx/vscode-lsaf-restapi-upload Source on GitHub
|
||||
20
public/en/yggdrasil-bittorrent-trackers.gmi
Normal file
20
public/en/yggdrasil-bittorrent-trackers.gmi
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
# Yggdrasil torrent trackers
|
||||
|
||||
## HTTP
|
||||
|
||||
* http://[21e:6565:9c87:a49d:dafa:92c1:b33f:f21]:1337/announce
|
||||
* http://[316:c51a:62a3:8b9::5]/announce
|
||||
|
||||
## UDP
|
||||
|
||||
* udp://[302:68d0:f0d5:b88d::fdb]:6969
|
||||
|
||||
## Links
|
||||
|
||||
=> https://github.com/YGGverse/yggdrasil-trackers
|
||||
=> https://yggdrasil-network.github.io/services.html#bittorrent
|
||||
=> http://[222:a8e4:50cd:55c:788e:b0a5:4e2f:a92c]/yggdrasil:sites_and_services:other_network_services
|
||||
|
||||
### See also
|
||||
|
||||
=> mycelium-bittorrent-trackers.gmi Mycelium torrent trackers
|
||||
31
public/en/youtube-downloads-with-yt-dlp.gmi
Normal file
31
public/en/youtube-downloads-with-yt-dlp.gmi
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
# YouTube downloads with yt-dlp
|
||||
|
||||
## Download in max resolution
|
||||
|
||||
``` bash
|
||||
yt-dlp CHANNEL_URL|PLAYLIST_URL|VIDEO_URL
|
||||
```
|
||||
|
||||
## Change default resolution to 1080
|
||||
|
||||
``` bash
|
||||
yt-dlp CHANNEL_URL|PLAYLIST_URL|VIDEO_URL -S res:1080
|
||||
```
|
||||
|
||||
## Download to location by source meta mask
|
||||
|
||||
``` bash
|
||||
yt-dlp CHANNEL_URL/playlists -o '%(uploader)s/%(playlist)s/%(title)s.%(ext)s'
|
||||
```
|
||||
|
||||
## Extract audio
|
||||
|
||||
``` bash
|
||||
yt-dlp CHANNEL_URL|PLAYLIST_URL|VIDEO_URL --extract-audio --audio-format vorbis
|
||||
```
|
||||
|
||||
## Get help
|
||||
|
||||
``` bash
|
||||
yt-dlp --help
|
||||
```
|
||||
5
public/en/zip-modified-files-only.gmi
Normal file
5
public/en/zip-modified-files-only.gmi
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
# Zip modified files only
|
||||
|
||||
``` bash
|
||||
zip modified-files.zip $(git ls-files --modified)
|
||||
```
|
||||
5
public/index.gmi
Normal file
5
public/index.gmi
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
# p.s.
|
||||
|
||||
=> uk/index.gmi Українська
|
||||
=> ul/index.gmi Ukrajins'ka
|
||||
=> en/index.gmi English
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
# Про сервер Fediverse в альтернативних мережах
|
||||
|
||||
Я давно користуюсь Fediverse, але свій інстанс - підняв відносно недавно: приблизно пів року тому. При чому, його було створено у якості експерименту з працездатності екосистеми ActivityPub в рамках оверлейної мережі Yggdrasil як спроба не просто зробити веб-проксі, а організації локального сузір'я.
|
||||
|
||||
Так як це був перший досвід, я ще збирався організувати доступ до нього з Інтернет (повноцінну між-серверну комунікацію) але згодом усвідомив, що цей протокол на таке не розрахований і навіть якщо це технічно можливо, адміністратори інших серверів потребуватимуть додаткового шару специфікації для такої взаємодії.
|
||||
|
||||
## Сервери
|
||||
|
||||
Їх вистачає: популярний Mastodon я не ставив бо не хотів морочитись з PostgreSQL та й в цілому, його розгортання виглядає для мене ледачого складно.
|
||||
|
||||
### Snac
|
||||
|
||||
Мені своєчасно порадили сервер Snac:
|
||||
=> https://codeberg.org/grunfink/snac2
|
||||
|
||||
Він є розрахованим не тільки на маленький персональний сервер без зовнішніх реєстрацій, а ще й не потребує бази даних, при тому клієнт функціонує без JS і до цього сервера є доволі якісні теми оформлення, наприклад Pika:
|
||||
=> https://codeberg.org/voron/snac-style/raw/branch/master/pika.css
|
||||
|
||||
Написаний Snac мовою C.
|
||||
|
||||
Функціонування (слідування, коментарі, бусти, приватні повідомлення тощо) в локальній мережі було успішно перевірено на живих вузлах Yggdrasil в комбінаціях:
|
||||
|
||||
* Snac (IPv6) / Snac (IPv6)
|
||||
* Snac (IPv6) / Snac (DNS)
|
||||
* Snac (IPv6) / Mitra (IPv6)
|
||||
* Snac (IPv6) / Mitra (DNS)
|
||||
|
||||
=> personal-snac-instance-for-yggdrasil-network.gmi Налаштування Fediverse-сервера Snac для мережі Yggdrasil
|
||||
|
||||
Мій інстанс для тестування:
|
||||
|
||||
=> http://[302:68d0:f0d5:b88d::fed] 302:68d0:f0d5:b88d::fed
|
||||
* взаємний фоловінг по запиту
|
||||
|
||||
### Mitra
|
||||
|
||||
Вже після встановлення Snac, я відкрив для себе Mitra:
|
||||
=> https://codeberg.org/silverpill/mitra
|
||||
|
||||
Цей сервер вимагає PostgreSQL, JS для стандартного клієнта і включає в себе навороти для автоматичної реєстрації та (мабуть) менеджменту користувачів. Я планую його спробувати потім, мені подобається його простий інтерфейс, користуюсь для свого Інтернет-профілю, який спочатку створив для тестів а потім там й лишився "жити".
|
||||
|
||||
Окремо згадую про це програмне рішення, тому що його вдалось протестувати в між-серверній комунікації з одним з реальних користувачів мережі. Також в нього була якимось чином налаштована взаємодія з Інтернет-федерацією. Подробиці цього збочення я не знаю, але довкола нашого експерименту, розробниками рушія Mitra було проявлено цікавість і спеціально натягнуто деякі адаптації по частині IPv6, тому в контексті цей сервер вартий уваги, а кому цікаві подробиці - зконтактуйте з
|
||||
```
|
||||
@madamada@mitra.void.my
|
||||
```
|
||||
* Yggdrasil
|
||||
|
||||
### Tootik
|
||||
|
||||
Окремо з цікавих платформ, я б ще відмітив сервер для протоколу Gemini - Tootik:
|
||||
=> https://github.com/dimkr/tootik
|
||||
|
||||
Його бекенд, як і передбачає ActivityPub, взаємодіє по HTTP/JSON, але на рівні користування там буде інтерфейс Gemini на 1965 порті з TLS.
|
||||
|
||||
Згадую про дане рішення в контексті того, що альтернативними мережами часто користуються з метою приватності, тому протокол Gemini тут може мати деяку нішу користувачів.
|
||||
|
||||
## Ідентифікатори хостів
|
||||
|
||||
Власне, саме цікаве і чому взагалі я задумав написати цей матеріал.
|
||||
|
||||
Щоб створити свій інстанс, вам потрібно ідентифікувати свій вузол як `user@host`. Коли ви це зробите, то вже не зможете безпроблемно його змінити потім, бо інші сервери федерації втратять зв'язок з вами. Тому він повинен бути обраний один раз і обраний правильно.
|
||||
|
||||
### DNS
|
||||
|
||||
ActivityPub розроблявся як протокол високого рівня для комунікації засобами класичної мережі Інтернет з DNS, у той час як мережах типу Yggdrasil прийнято користуватись IPv6 а домен - вже надавати опцією.
|
||||
|
||||
Локальна мережа з ідентифікацією DNS, здавалось би дозволяє легко змінювати адреси IP або навіть перескочити з мережі Yggdrasil на Mycelium, а з того - на ще якусь нову екосистему. Але за цими перескоками повинні слідувати не тільки ваші читачі, але й сервери федерації. Тому сумнівно, якщо це не якийсь спеціалізований на одну мережу домен `.ygg` в Alfis DNS, що тільки відсіче потенційну частину сегменту, яка ним не користується.
|
||||
|
||||
### IP
|
||||
|
||||
Свій ID я вирішив робити на IPv6 адресі мережі Yggdrasil бо такий формат, на відміну від домена, не може бути протермінований з часом (так, я можу зникнути на рік два і неочікувано для себе повернутись до мережі через десять).
|
||||
|
||||
З іншого боку, перманентні IP на основі криптографії - теж не панацея: ключі можуть бути загублені, випадково опубліковані тощо, а тому можуть потенційно потребувати генерації нових.
|
||||
|
||||
### Адреси підмереж
|
||||
|
||||
В мене ще лишається відкритим питання з адресами підмереж, бо ті є менш стійкими до колізій і такими, що потенційно можуть бути випиляні з майбутніх релізів роутера. Так, вони зручні, але сьогодні я б радив користуватись основними адресами для ідентифікації сервера, коли це можливо.
|
||||
|
||||
## Гібридна маршрутизація
|
||||
|
||||
На початку матеріалу зауважив, що особисто для себе - відмовився від ідеї мульти-мережної комунікації для свого інстансу, спробувавши просто ініціювати локальне сузір'я, галактику, фізично ізольованої на рівні ActivityPub від інших мереж. Але зараз, спостерігаю занепад обраної мною мережі Yggdrasil, вже експериментую з Mycelium, і вже завтра - буду експериментувати з наступною. Тому трохи розкрию свої думки стосовно гібридного формату вузла.
|
||||
|
||||
Вже після запуску сервера в альтернативній мережі (або мережах з налаштованим проксі для між-серверного API), постане питання поширення посилань. Адже ви захочете ділитись публікаціями з друзями в Інтернет, Yggdrasil, I2P та інших екосистемах. Бажано, це має бути якесь одне канонічне посилання, яке приведе користувача до цільової сторінки в незалежності від налаштувань його маршрутизації і функціонування самої мережі на момент відвідування.
|
||||
|
||||
Були думки щодо організації центрального сервісу "коротких посилань" по типу колишнього bit.ly який підтримуватиме усі можливі альтернативи і для кожної з них надаватиме веб-проксі за форматом хосту...
|
||||
|
||||
З іншого боку, можна створити ще один "шейред роутер" як окремий протокол та програму для нього, саме з метою обслуговування гібридних сервісів без реалізації їх маршрутизації. У цьому питанні явно не вистачає сучасних рішень, адже зберігається тенденція до створення нових мереж та деградації старих, як це сталось з CJDNS і сьогодні відбувається з Yggdrasil. Технічно, діапазон IPv6 надає широке поле для експериментальних роутерів, їх кількість в умовах сучасних перешкод мережі буде тільки зростати, тому це питання є відкритим.
|
||||
|
||||
## Висновки
|
||||
|
||||
Особисто для себе, вирішив не міксувати екосистеми і вести ізольовані тематичні ресурси по кожній з них, намагаючись ділитись посиланнями в рамках тої екосистеми, для якої створено інстанс. Звичайно, на практиці виходить інакше, станом на сьогодні, назвати локальний інстанс - соціальним складно, утім якщо ви цієї соціальної взаємодії не шукаєте на глобальному рівні, то чому б не спробувати.
|
||||
|
||||
## Посилання
|
||||
|
||||
=> https://devzone.org.ua/post/pro-server-fediverse-v-alternatyvnykh-merezakh Веб-адаптація матеріалу на DevZone (з коментарями)
|
||||
|
||||
### Дивіться також
|
||||
|
||||
=> yggdrasil-is-network-with-distributed-routing.gmi Yggdrasil - мережа з децентралізованою маршрутизацією
|
||||
92
public/uk/alfis-dns-domain-registration-in-blockchain.gmi
Normal file
92
public/uk/alfis-dns-domain-registration-in-blockchain.gmi
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
# Alfis DNS - реєстрація домену в блокчейн
|
||||
|
||||
Alfis DNS - децентралізована система доменних імен з реєстром в блокчейн.
|
||||
|
||||
Резольвер та клієнтська частина написані на мові Rust.
|
||||
|
||||
Для реєстрації домену використовуються наступні зони:
|
||||
|
||||
* .anon *
|
||||
* .btn
|
||||
* .conf
|
||||
* .index
|
||||
* .merch
|
||||
* .mirror
|
||||
* .mob
|
||||
* .screen
|
||||
* .srv
|
||||
* .ygg *
|
||||
|
||||
* зарезервовані для адрес мережі Yggdrasil, що виключає випадковий перехід з таких адрес на хости Clearnet.
|
||||
|
||||
Для запобігання кіберсквотингу використовується модель PoW і частково - PoS, генерація нових доменів також обмежена добовим інтервалом, а на один персональний ключ можна згенерувати не більше 10 доменів (що насправді має досить спірне підґрунтя).
|
||||
|
||||
Тим не менше, система досить зручна для локальних мереж, оскільки дозволяє створити безкоштовний домен на один рік без необхідності реєстрації персональних даних та залежності від центрального серверу. А розмір блокчейну при поточній кількості близько 1000 доменів складає приблизно 7 Мб.
|
||||
|
||||
В середньому, на комп'ютері з процесором i5, новий домен генерується від декількох до 12 годин; утім спочатку потрібно згенерувати персональний ключ, до якого потім цей домен буде прив'язаний. До закінчення року, потрібно змайнити домен повторно, використовуючи існуючий ключ, раніше робити це не має сенсу, бо пролонгація рахується від часу створення блоку.
|
||||
|
||||
## Встановлення
|
||||
|
||||
Встановлення відбувається досить просто, є готові бінарні пакети та репозиторії.
|
||||
|
||||
При збірці, з початкового коду, доведеться встановити останню версію rustc що зручно використовуючи пакет rustup.
|
||||
|
||||
В іншому, виконується стандартна процедура cargo:
|
||||
|
||||
```
|
||||
git clone https://github.com/Revertron/Alfis.git
|
||||
cd Alfis
|
||||
cargo build --release
|
||||
```
|
||||
|
||||
## Налаштування
|
||||
|
||||
Запускаючи клієнт з графічною оболонкою, буде автоматично налаштовано резольвер.
|
||||
|
||||
Для систем типу Ubuntu, ймовірно доведеться вивільнити зайнятий порт 53.
|
||||
|
||||
Утім, графічний інтерфейс зручно використовувати виключно для адміністрування доменів та майнінгу, а сам резольвер розмістити десь на VPS та вказати до нього конфігурацію:
|
||||
|
||||
### В системах з systemd-resolved
|
||||
|
||||
```
|
||||
#/etc/systemd/resolved.conf
|
||||
[Resolve]
|
||||
DNS=IP
|
||||
Domains=~.
|
||||
```
|
||||
|
||||
Після змін, потрібно оновити кеш командою:
|
||||
|
||||
```
|
||||
systemctl restart systemd-resolved
|
||||
```
|
||||
|
||||
### В системах без systemd
|
||||
|
||||
```
|
||||
#/etc/resolv.conf
|
||||
nameserver xx.xx.xx.xx
|
||||
```
|
||||
|
||||
### FireFox
|
||||
|
||||
Браузер нічого не знає про діапазон імен Alfis DNS, тому при введені таких адрес, буде відправляти користувача в пошук.
|
||||
|
||||
Щоб виправити це, потрібно додати в about:config, наприклад для зони .ygg - наступну опцію:
|
||||
|
||||
```
|
||||
browser.fixup.domainsuffixwhitelist.ygg = true
|
||||
```
|
||||
|
||||
## Особистий досвід
|
||||
|
||||
* Alfis DNS хоч і працює з типовими адресами, але вимагає наявності встановленого або підключеного вузла для клієнтів. З цієї ж причини виникає і проблема сертифікації, наприклад засобами Certbot / Let's Encrypt.
|
||||
* В намірах зменшити розмір блокчейну, автор явно перегнув із захистом від зловживань сквотерами, від чого іноді доводиться чекати випадкові вузли, що підпишуть блок. А сама модель захисту явно грає на руку тим, хто в сквотингу зацікавлені (володіючи відповідним обчислювальним ресурсом). Під час останнього такого "зависання" частина користувачів була обурена бездіяльністю автора у відповідь на повторний інцидент і вірогідно відмовилась від цього і до того непопулярного рішення.
|
||||
* Внутрішньої монети блокчейн немає, утім потенційно може мати деякий економічний потенціал з використанням бартеру (засобами трансферу)
|
||||
* Наразі проєкт варто сприймати виключно як експериментальну альтернативу централізованим сервісам для ентузіастів, який фактично виконує ту само роль, що й /etc/hosts
|
||||
|
||||
## Посилання
|
||||
|
||||
=> https://github.com/Revertron/Alfis Репозиторій проєкту на GitHub
|
||||
=> https://viewer.alfis.name Неофіційний експлорер
|
||||
45
public/uk/asocial-p2p.gmi
Normal file
45
public/uk/asocial-p2p.gmi
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
# Граблі соціального P2P
|
||||
|
||||
Це мій особистий висновок в контексті соціальних платформ, які у свій час мали на меті створити "вільний інтернет" для вільних людей, зокрема - такі вже сьогодні мертві проєкти як twister, OpenBazaar, ZeroNet та інші. А можливо завтра - не так давно анонсована перша стабільна версія децентралізованої Git платформи Radicle.
|
||||
|
||||
## BitTorrent / DHT
|
||||
|
||||
Нічого революційного за останні роки еволюції пірингових технологій не відбулось. Мабуть, єдиним напівживим піринговим напрямком, все ще лишається обмін великими файлами через BitTorrent / DHT засобами UPnP, що дозволяє клієнтові користуватись шириною каналу, а серверу - балансувати трафік на піках, допоки пір не отримає своє та не закриє додаток, видаливши потім і сам файл.
|
||||
|
||||
## Залежність від сервісних вузлів
|
||||
|
||||
Трекери, сіди, ноди ретрансляції...
|
||||
|
||||
Ніхто за дарма не буде обслуговувати серйозний об'єм даних. Звісно, можна знайти "не мамонта", хто вірить в щось, паразитувати на його ноді, деякий час..
|
||||
|
||||
Підняв віддалену ноду Radicle для експерименту на мотивації стати сідом, а та з'їла все вільне місце на диску. Можливо, є певна опція, щоб лімітувати простір чи зберігати якісь фрагментовані дані (pieces), але тоді для мережі потрібна більша кількість вузлів, що забезпечать її 100% покриття. Тут я вже мовчу про оверхед системних даних, що стосуються актуалізації даних (CRUD) і мережевої роботи самого рою.
|
||||
|
||||
Якщо мені потрібен повноцінний сервер з виділеним IP, то питання: чому просто не поставити собі Gitea?
|
||||
|
||||
## Очікування пірів
|
||||
|
||||
В пірингових мережах завжди доводиться чекати когось на роздачу, яка відбувається, коли вже й не потрібно. Або ж знову таки орендувати сервер VPN, щоб спробувати знайти контент в заблокованих глобальним фаєрволом локаціях. Хоча на практиці, IP "не сервісних" вузлів змінюється так швидко, що й VPN не є панацеєю. В сучасному світі прогрес не стоїть на місці, люди користуються мобільним інтернетом, а той еволюціонує для балансування навантажень між різними станціями, генеруючи тони мертвих через годину IP.
|
||||
|
||||
З цієї ж причини, багато даних просто втрачається. Якщо ви хочете загубити на рандомному і цілком тимчасовому пірі шматок опублікованих даних, p2p - вдалий вибір.
|
||||
|
||||
## BlockChain
|
||||
|
||||
Тут здавалось би, рішенням може стати BlockChain, але це веде у ті само ворота, коли об'єм даних розростається а вартість зберігання зростає. При цьому, сама технологія блокчейн доволі чутлива до консенсусу: будь які зміни останнього вимагають згоди від усіх учасників та оновлення ними локальних копій програмного забезпечення, що не рідко спонукає до фрагментування форками.
|
||||
|
||||
Іноді я навіть не знаю, що витратніше для процесору: періодичний майнинг чи постійна актуалізація DHT. Багато p2p платформ використовують для своєї роботи і BlockChain і окремий сервер(и) DHT, а ще SSL інтерфейс для останнього і сервер UPnP. Відповідно це піднімає вимоги до вашого знову ж таки виділеного серверу, бо на локальному, без добровольців-садомазохістів мережа просто не працюватиме. А ті, на практиці, онлайн не довго, бо знаходять собі нову забаву, що вимагає 100% віддачі ресурсів попередньої.
|
||||
|
||||
## Mesh
|
||||
|
||||
Іншим цікавим напрямком, є оверлейні мережі типу Yggdrasil, що використовують піринг для побудови автоматизованого роутингу. Здебільшого вони зручні в ситуаціях, коли з якихось причин, протокол UPnP не доступний або певний порт блокується провайдером. Але й тут, подібно до VPN, потрібні вихідні вузли, тобто є залежніть від когось, а цей хтось - по суті, звичайний сервер.
|
||||
|
||||
На мою думку, потреба в оверлейних мережах відпаде з інтеграцією ISP протоколу IPv6, що дозволить кожному отримати свою виділену адресу і закрити це питання разом з його надлишковою інфраструктурою.
|
||||
|
||||
## Висновки
|
||||
|
||||
Таким чином, поки хтось не оформить 5-10 серверів початковою вартістю хоч в одну акцію GitHub (в контексті Radicle), воно просто не функціональне, при всій моїй лояльності до напрямку p2p.
|
||||
|
||||
Вже яку тисячу разів я стаю на ці граблі: ну немає ніякої свободи у цьому, суцільні обмеження, купа зайвого трафіку, обчислень і власного часу. Воно класно тільки тим, що зручно реплікується по хешу, але знову таки якщо задача децентралізувати то простіше руками чи скриптом розкидати на client/server.
|
||||
|
||||
Все одно розподілені/анархічні ноди потребують сервер у якійсь цілком собі монархічній країні. Ще раз нагадування собі про те, що "втекти" кудись вирішує питання, у кращому випадку, тільки на деякий час.
|
||||
|
||||
Сама пірингова технологія, все ще може бути корисною у спеціалізованих сферах, для яких власне вона і розроблялась. Додаткові можливості з повітря не беруться, а свої громадянські права і свободу - досі потрібно виборювати, на жаль.
|
||||
55
public/uk/btracker-bittorrent-tracker-in-rust.gmi
Normal file
55
public/uk/btracker-bittorrent-tracker-in-rust.gmi
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
# βtracker - BitTorrent агрегатор на базі Rust
|
||||
|
||||
> Даний матеріал писався як гайд для локальної спільноти адміністраторів альтернативних мереж, утім, я знайшов його потенційно цікавим для широкого загалу: зокрема для тих, хто бажає підняти свій торент трекер і автоматизований Веб-каталог з функцією пошуку та статистикою роздач на базі інфраструктури Rust.
|
||||
|
||||
βtracker (beta-tracker) - BitTorrent каталог агрегаційного типу з Веб-інтерфейсом на базі фреймворку Rocket (https://rocket.rs), що є продовженням попереднього проєкту YGGtracker але на відміну від останнього - повністю автоматизований.
|
||||
|
||||
Індекс тут складається на базі додаткових компонентів:
|
||||
=> https://github.com/YGGverse/aquatic/tree/yggverse/crates/udp форк UDP трекера "aquatic", який генерує дамп інфо-хешів у бінарному форматі API
|
||||
=> https://github.com/YGGverse/aquatic-crawler спеціально написаний кравлер "aquatic-crawler"
|
||||
|
||||
## Принцип роботи
|
||||
|
||||
Схематично, робота усієї системи зображена в README:
|
||||
```
|
||||
torrent client > aquatic_udp > infohash.bin < aquatic-crawler > * /preload/info-hash.torrent > β
|
||||
torrent client <-----------------------| * /preload/info-hash/data |
|
||||
<-------------------------------------| * /preload/.info-hash/tmp |
|
||||
<-------------------------- scrape -------------------------------|
|
||||
```
|
||||
* на схемі βtracker є останнім оператором даних справа.
|
||||
|
||||
Таким чином, торент-клієнти передають дані на UDP трекер, звідки (його форк) генерує бінарний API дамп `infohash.bin` з опціональною періодичністю, який в свою чергу читає кравлер і резольвить вказані дані (мета дані торент файлів, опціонально підвантажує зображення, txt файли, логи та інші) у спільну файлову систему, звідки їх вже читає та парсить агрегатор βtracker, тим само формуючи пошуковий індекс і Web UI.
|
||||
|
||||
Наразі вся система є раннім прототипом, і при вдалому її тестуванні, планується створити спільну бібліотеку файлової БД, зі стандартизованим API для всіх компонентів системи, що працюють з файлами асинхронно.
|
||||
|
||||
## Мережі
|
||||
|
||||
βtracker розроблявся для мережі Yggdrasil (https://yggdrasil-network.github.io), але на відміну від YGGtracker, може без проблемно працювати з Інтернет / IPv4 включно, а також споріднених оверлейних мережах типу Mycelium (https://github.com/threefoldtech/mycelium).
|
||||
|
||||
## Проблеми
|
||||
|
||||
В рамках того, що коментарі та інша мета-інформація не є частиною стандартного словника BitTorrent:
|
||||
=> https://wiki.theory.org/BitTorrentSpecification#Info_Dictionary
|
||||
ці дані втрачаються при резольві байтів торент файла з інфо-хешу.
|
||||
|
||||
Оскільки сам інфо-хеш формує унікальність роздачі, отримати такі дані з першого зустрічного піра не варіант, навіть якщо це технічно можливо при наприклад запиті такої інформації через сокет за рамками протоколу BitTorrent. Утім, й наявних даних цілком вистачає для побудови навігації та пошуку торентів (включно з індексованим вмістом) у невеличких мережах.
|
||||
|
||||
## Додаткова функціональність
|
||||
|
||||
Так як URI сторінок торентів є унікальними для усієї мережі BitTorrent інфо-хешами, технічно, можливо реалізувати для них локальні соціальні функції: коментарі, лічильник завантажень, вподобання тощо. Але наразі така функціональність не запланована, щонайменше до першої стабільної версії усіх компонентів системи.
|
||||
|
||||
## Інстанси
|
||||
|
||||
Поки, для тестування усіх компонентів системи, функціонує один інстанс Yggdrasil:
|
||||
=> http://[302:68d0:f0d5:b88d::fdb]
|
||||
=> http://tracker.ygg Alfis DNS
|
||||
|
||||
UPD. днями з'явилась реалізація серверної частини для протоколу Gemini та відповідний інстанс:
|
||||
=> https://github.com/YGGverse/btracker-gemini
|
||||
=> gemini://[302:68d0:f0d5:b88d::fdb]
|
||||
=> gemini://tracker.ygg Alfis DNS
|
||||
|
||||
## Посилання
|
||||
|
||||
=> https://github.com/yggverse/btracker GitHub
|
||||
190
public/uk/chesslablab-open-source-chess-in-php.gmi
Normal file
190
public/uk/chesslablab-open-source-chess-in-php.gmi
Normal file
|
|
@ -0,0 +1,190 @@
|
|||
# ChesslaBlab - шахи онлайн з відкритим кодом на PHP
|
||||
|
||||
ChesslaBlab - це проєкт з відкритим кодом на PHP, для розгортання шахового серверу з нуля та клієнтська частина на Symfony - для вивчення стратегій, гри онлайн з комп'ютером або друзями.
|
||||
|
||||
Являє собою невибагливу до серверних потужностей та більш спрощену альтернативу Lichess.
|
||||
|
||||
У якості рушія штучного інтелекту використовується сервер Stockfish:
|
||||
|
||||
=> https://github.com/official-stockfish/Stockfish
|
||||
|
||||
ChesslaBlab може бути цікавим для:
|
||||
|
||||
* розробників
|
||||
* керівників освітніх програм
|
||||
* тренерів шахових клубів
|
||||
* просто бажаючих проводити власні турніри, розгорнувши багатокористувацький сервер для гри в браузері на мінімальному тарифі VPS
|
||||
|
||||
Варто зауважити, що обчислення сценаріїв виконується в режимі "server-side", тому такий проєкт оптимально підійде для ігор з невеликою кількістю одночасних сесій, наприклад в локальній мережі.
|
||||
|
||||
## Сервер
|
||||
|
||||
Для розгортання серверної частини, використовується "chess-server":
|
||||
|
||||
=> https://github.com/chesslablab/chess-server
|
||||
|
||||
що реалізує бібліотеку "php-chess":
|
||||
|
||||
=> https://github.com/chesslablab/php-chess
|
||||
|
||||
В системах Debian, спочатку потрібно встановити наступні залежності:
|
||||
|
||||
```
|
||||
apt install git php composer stockfish
|
||||
```
|
||||
|
||||
Для безпечного запуску, краще створити окремого користувача:
|
||||
|
||||
```
|
||||
useradd -m chesslablab
|
||||
su chesslablab
|
||||
```
|
||||
|
||||
Клонуємо репозиторій та оновлюємо залежності Composer:
|
||||
|
||||
```
|
||||
git clone https://github.com/chesslablab/chess-server.git
|
||||
cd chess-server
|
||||
composer update
|
||||
```
|
||||
|
||||
Копіюємо приклад конфігурації в продакшн:
|
||||
|
||||
```
|
||||
cp .env.example .env
|
||||
```
|
||||
|
||||
Файл містить налаштування для двох типів з'єднань:
|
||||
|
||||
1. "WSS" - захищене з'єднання через веб-сокет (потребує додатково створення сертифікатів)
|
||||
2. "WS" - незахищене, в принципі цей варіант буде простішим для початку
|
||||
|
||||
Вказуємо актуальні адреси для обраного способу, після чого відкриваємо відповідні порти в "iptables" наприклад за допомогою утиліти "ufw":
|
||||
|
||||
```
|
||||
ufw allow 8443
|
||||
ufw allow 8085
|
||||
```
|
||||
|
||||
Для кожного типу з'єднань, є свій метод (скрипт) запуску, описаний в документації:
|
||||
|
||||
=> https://chess-server.docs.chesslablab.org
|
||||
|
||||
Наприклад, для "WS", я користуюсь реалізацією сокет-сервера на PHP - Ratchet:
|
||||
|
||||
=> https://github.com/ratchetphp/Ratchet
|
||||
|
||||
і наступною командою:
|
||||
|
||||
```
|
||||
php cli/ratchet/ws.php
|
||||
```
|
||||
|
||||
Також, зручно створити сервіс "systemd":
|
||||
|
||||
``` /etc/systemd/system/chesslablab.service
|
||||
[Unit]
|
||||
Description=chesslablab
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=chesslablab
|
||||
ExecStart=/usr/bin/php /home/chesslablab/chess-server/cli/ratchet/ws.php
|
||||
StandardOutput=file:/home/chesslablab/chess-server-debug.log
|
||||
StandardError=file:/home/chesslablab/chess-server-error.log
|
||||
Restart=on-failure
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
Після чого додати його в авто-запуск:
|
||||
|
||||
```
|
||||
systemctl daemon-reload
|
||||
systemctl enable chesslablab
|
||||
systemctl start chesslablab
|
||||
```
|
||||
|
||||
Перевірити роботу служби на порті можна командою:
|
||||
|
||||
```
|
||||
netstat -tulpn | grep LISTEN
|
||||
```
|
||||
|
||||
## Клієнт
|
||||
|
||||
За весь час розробки, проєкт мав декілька клієнтів, зокрема реалізацію на React.js, яка нещодавно була переведена у стан архівної:
|
||||
|
||||
=> https://github.com/chesslablab/react-chess
|
||||
|
||||
Наразі, актуальним клієнтом є багатосторінкова реалізація на базі фреймворку Symfony, розробка яклшл ведеться в репозиторії "website":
|
||||
|
||||
=> https://github.com/chesslablab/website
|
||||
|
||||
Встановлення досить просте, якщо додані залежності серверу, достатньо виконати наступні команди:
|
||||
|
||||
```
|
||||
cd /home/chesslablab
|
||||
git clone https://github.com/chesslablab/website.git
|
||||
cd website
|
||||
composer update
|
||||
cp assets/env.example.js assets/env.js
|
||||
php bin/console importmap:install
|
||||
```
|
||||
|
||||
Змінюємо у скопійованому файлі "assets/env.js" потрібні нам адреси відповідно до налаштувань сервера і генеруємо оптимізований кеш для веб-застосунку:
|
||||
|
||||
```
|
||||
php bin/console asset-map:compile
|
||||
```
|
||||
|
||||
При змінах в стандартному файлі Symfony ".env" в середовищі "production", скидаємо кеш командою:
|
||||
|
||||
```
|
||||
APP_ENV=prod APP_DEBUG=0 php bin/console cache:clear
|
||||
```
|
||||
|
||||
Налаштування Nginx - таке само як і для типового проєкту на Symfony.
|
||||
|
||||
Для проєкту в локальній мережі IPv6 Yggdrasil / Alfis DNS, я користуюсь наступною конструкцією "WS" (достатньо змінити домен на той, що вказано в налаштуваннях клієнта):
|
||||
|
||||
```
|
||||
server {
|
||||
listen [::]:80;
|
||||
|
||||
allow 0200::/7;
|
||||
deny all;
|
||||
|
||||
server_name chesslablab.ygg chesslablab.ygg.at;
|
||||
|
||||
root /home/chesslablab/website/public;
|
||||
|
||||
location / {
|
||||
try_files $uri /index.php$is_args$args;
|
||||
}
|
||||
|
||||
location ~ ^/.+\.php(/|$) {
|
||||
|
||||
# php -v
|
||||
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
|
||||
|
||||
include fastcgi_params;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
fastcgi_param APP_ENV prod;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Якщо все зроблено правильно, то можна відкрити сайт і почати гру з комп'ютером.
|
||||
|
||||
У разі проблем, першим ділом відкриваємо консоль браузеру "Ctrl+Shift+i" та дивимось стан підключення.
|
||||
Якщо підключення до сокету успішне, тоді потрібно дивитись безпосередньо серверні журнали за шляхами, які вказані в секціях "StandardOutput" та "StandardError" сервісу "systemd".
|
||||
|
||||
Долучайтесь до розробки на GitHub - проєкт має хороший фідбек від розробника!
|
||||
|
||||
## Посилання
|
||||
|
||||
=> https://chesslablab.org Офіційний сайт ChesslaBlab
|
||||
=> https://github.com/chesslablab Сторінка на GitHub
|
||||
32
public/uk/create-half-life-graffiti-logo-in-gimp.gmi
Normal file
32
public/uk/create-half-life-graffiti-logo-in-gimp.gmi
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
# Створення графіті Half-Life в GIMP
|
||||
|
||||
В мультиплеєрі Half-Life можна малювати графіті (або логотипи)
|
||||
|
||||
Для цього, в стандартній конфігурації, використовується клавіша "T".
|
||||
|
||||
Обрати таке зображення можна в меню "Multiplayer" → "Customize",
|
||||
але якщо жодне з них не відповідає бажаному, є можливість зробити його самому, в редакторі з відкритим кодом - GIMP!
|
||||
|
||||
Файл графіті / логотипу для Half-Life має бути у відтінках сірого, розміром 64х64 пікселя та у форматі "BMP".
|
||||
При тому, чорний колір у поточній схемі - буде відповідати 100% прозорості.
|
||||
Палітру можна потім обрати безпосередньо в інтерфейсі ігрових налаштувань.
|
||||
|
||||
Щоб створити логотип на базі існуючого кольорового зображення, наприклад:
|
||||
|
||||
=> https://github.com/YGGverse/hl-customs/blob/main/icons/ipv6/128x128.png?raw=true Емблема "Half-Life IPv6"
|
||||
|
||||
Відкриваємо його в редакторі GIMP і виконуємо наступні кроки:
|
||||
|
||||
1. "Image" → "Scale Image" → "64×64 / Quanlity: Linear"
|
||||
2. "Layer" → "Transparency" → "Remove Alpha Channel"
|
||||
3. "Colors" → "Components" → "Decompose"
|
||||
4. "Colors" → "Invert"
|
||||
5. "File" → "Export As.." → зберігаємо до "valve/logos/filename.bmp"
|
||||
|
||||
Якщо все зроблено правильно, результат буде наступним:
|
||||
|
||||
=> https://raw.githubusercontent.com/YGGverse/hl-customs/main/icons/ipv6/valve/logos/ipv6.bmp Логотип "Half-Life IPv6"
|
||||
|
||||
## Дивіться також
|
||||
|
||||
=> half-life-on-linux-using-xash3d-fwgs-engine.gmi Half-Life в Linux на базі рушія Xash3D / FWGS
|
||||
122
public/uk/dns-less-email-server-for-the-local-networks.gmi
Normal file
122
public/uk/dns-less-email-server-for-the-local-networks.gmi
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
# Організація поштової скриньки для локальних мереж без DNS
|
||||
|
||||
Даний матеріал є адаптацією інструкції для користувачів локальної спільноти адміністраторів альтернативних мереж. Може стати в нагоді, якщо ви бажаєте створити власний поштовий сервер для локальної групи користувачів на підприємстві або для дому, без використання сторонніх серверів Google (та інших провайдерів) для переписки засобами DeltaChat або іншого клієнта, що підтримує протоколи SMTP/IMAP.
|
||||
|
||||
Подібним займаюсь вперше, матеріал може доповнюватись, але в цілому, мій персональний сервер на базі локальної мережі Yggdrasil - вже працює. Користуючись мережами Yggdrasil та/або Mycelium, ви також можете отримувати і надсилати пошту з локального простору через їх вбудований оверлейний режим: тобто пересилати листи через Інтернет без виділеного IP за NAT.
|
||||
|
||||
* якщо плануєте користуватись Yggdrasil але для вас ця інструкція виглядає складною, зверніть увагу на більш простий, коробковий варіант для локальних мереж - Yggmail, але він є швидше месенджером з API для поштових клієнтів з лімітом на вкладення в 1 Мб, а не повноцінним поштовим сервером; до того ж реалізує не стандартні адреси, що може стати проблемою сумісності з альтернативними клієнтами, які валідують хост без підтримки локальних псевдонімів
|
||||
|
||||
## Створення користувача пошти
|
||||
|
||||
Є багато способів адміністрування скриньок, але я обрав самий простий: системний, за паролем:
|
||||
|
||||
``` bash
|
||||
useradd -m USER
|
||||
passwd USER
|
||||
echo "root: USER" >> /etc/aliases
|
||||
```
|
||||
* USER - замініть на вашого користувача
|
||||
* для логіну буде використовуватись саме "юзернейм" а не "юзернейм@хост", оскільки технічно я хочу потім зробити прийом пошти з Yggdrasil та Mycelium на один і той же системний обліковий запис
|
||||
* вказаний пароль буде також використовуватись для авторизації в клієнті
|
||||
|
||||
## Dovecot
|
||||
|
||||
``` bash
|
||||
apt install dovecot-core dovecot-imapd
|
||||
```
|
||||
|
||||
### /etc/dovecot/dovecot.conf
|
||||
|
||||
Вимикаю IPv4, але "слухаю" всі мережі IPv6 (включно з Yggdrasil та у моєму випадку - Mycelium)
|
||||
|
||||
``` /etc/dovecot/dovecot.conf
|
||||
listen = ::
|
||||
```
|
||||
|
||||
### /etc/dovecot/conf.d/10-master.conf
|
||||
|
||||
``` /etc/dovecot/conf.d/10-master.conf
|
||||
service auth {
|
||||
unix_listener /var/spool/postfix/private/auth {
|
||||
mode = 0666
|
||||
user = postfix
|
||||
group = postfix
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Postfix
|
||||
|
||||
``` bash
|
||||
apt install postfix
|
||||
```
|
||||
|
||||
### /etc/postfix/main.cf
|
||||
|
||||
``` /etc/postfix/main.cf
|
||||
myhostname = localhost
|
||||
|
||||
smtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU)
|
||||
biff = no
|
||||
append_dot_mydomain = no
|
||||
readme_directory = no
|
||||
smtpd_use_tls=no
|
||||
compatibility_level = 3.6
|
||||
|
||||
smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated defer_unauth_destination
|
||||
|
||||
alias_maps = hash:/etc/aliases
|
||||
alias_database = hash:/etc/aliases
|
||||
|
||||
mydestination =
|
||||
relayhost =
|
||||
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
|
||||
mailbox_size_limit = 0
|
||||
recipient_delimiter = +
|
||||
inet_interfaces = all
|
||||
inet_protocols = ipv6
|
||||
|
||||
# деякі поради від спаму з мережі, але як вони працюють ще не знаю :)
|
||||
smtpd_etrn_restrictions=reject
|
||||
disable_vrfy_command = yes
|
||||
smtpd_helo_required = yes
|
||||
|
||||
# інтеграція з Dovecot
|
||||
smtpd_sasl_auth_enable = yes
|
||||
smtpd_sasl_type = dovecot
|
||||
smtpd_sasl_path = private/auth
|
||||
mailbox_command =
|
||||
```
|
||||
* опцію `smtpd_use_tls` вимкнено, тому що весь внутрішній трафік Yggdrasil (у моєму випадку) вже захищено на рівні транспорту; для класичних мереж - можна скористатись само-підписаним сертифікатом, додавши на нього виключення.
|
||||
|
||||
## Фаєрвол
|
||||
|
||||
Моя особиста конфігурація не передбачає прийом пошти від користувачів окрім локальних:
|
||||
|
||||
``` bash
|
||||
ufw allow from CLIENT_IP to any port 25 proto tcp
|
||||
ufw allow from CLIENT_IP to any port 143 proto tcp
|
||||
```
|
||||
* замінити CLIENT_IP на той, з якого підключатиметься клієнт DeltaChat
|
||||
|
||||
У випадку, якщо ви налаштовуєте скриньку для прийому відправлень від інших користувачів локальної мережі, можете додати виключення на його хост тієї мережі, якою користуєтесь, або замість фаєрволу - налаштувати доступ засобами SpamAssassin.
|
||||
|
||||
## DeltaChat
|
||||
|
||||
Налаштовуючи даний клієнт, вказуємо:
|
||||
* E-mail - у форматі RFC 5321, тобто з літералом IPv6, наприклад: user@[IPv6:xxx:xxxx:xxxx:xxxx::]
|
||||
* User SMTP/IMAP - такий як до `useradd` (без хосту)
|
||||
* Host SMTP/IMAP - ваш IPv6 в мережі Yggdrasil або Mycelium
|
||||
* Password - такий як до `passwd`
|
||||
* Обов'язково вказуємо стандартні порти, інакше DeltaChat використовує відмінні від 25/143
|
||||
* Усі види шифрування TLS вимикаємо
|
||||
|
||||
## Посилання
|
||||
|
||||
=> https://www.rfc-editor.org/rfc/rfc5321#section-4.1.3 Специфікація RFC 5321
|
||||
=> https://devzone.org.ua/post/orhanizatsiia-poshtovoyi-skrynky-e-mail-dlia-lokalnykh-merez-bez-dns Веб-адаптація матеріалу на DevZone (з коментарями)
|
||||
|
||||
### Дивіться також
|
||||
|
||||
=> yggdrasil-is-network-with-distributed-routing.gmi Yggdrasil - мережа з децентралізованою маршрутизацією
|
||||
=> yggmail-messenger-with-email-protocol.gmi Yggmail - месенджер з поштовим інтерфейсом
|
||||
37
public/uk/fail2ban-startup-failure-fix-on-debian-12.gmi
Normal file
37
public/uk/fail2ban-startup-failure-fix-on-debian-12.gmi
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
# Виправлення помилки запуску fail2ban в Debian 12
|
||||
|
||||
fail2ban - це утиліта на Python для захисту серверів від атак підбору паролів.
|
||||
|
||||
Вона сканує системні журнали на предмет шкідливої активності, та блокує підозрілі хости на заданий в налаштуваннях час.
|
||||
|
||||
Програма має базові налаштування і працює одразу після встановлення, стандартно блокуючи на десять хвилин доступ до "ssh" після п'ятої невдалої спроби входу.
|
||||
|
||||
Подивитись стандартні налаштування можна у файлі "/etc/fail2ban/jail.conf".
|
||||
|
||||
Утім, в системах Debian 12 існує відома проблема її запуску зі штатних репозиторіїв, що звершується з помилкою сервісу "systemd".
|
||||
|
||||
Виправити це досить просто виконавши наступні кроки.
|
||||
|
||||
1. Переконайтесь, що "python3-systemd" встановлено:
|
||||
|
||||
```
|
||||
apt install python3-systemd
|
||||
```
|
||||
|
||||
2. Додайте наступні налаштування у файл:
|
||||
|
||||
``` /etc/fail2ban/jail.local
|
||||
[DEFAULT]
|
||||
backend = systemd
|
||||
```
|
||||
|
||||
3. Перезавантажте сервіс:
|
||||
|
||||
```
|
||||
systemctl restart fail2ban
|
||||
```
|
||||
|
||||
## Посилання
|
||||
|
||||
=> https://github.com/fail2ban/fail2ban Офіційна сторінка fail2ban на GitHub
|
||||
=> https://github.com/fail2ban/fail2ban/issues/3292 Звіт про помилку #3292
|
||||
260
public/uk/first-impressions-of-cpp.gmi
Normal file
260
public/uk/first-impressions-of-cpp.gmi
Normal file
|
|
@ -0,0 +1,260 @@
|
|||
# Мої перші враження від C++
|
||||
|
||||
Я займаюсь професійною Веб розробкою вже близько п'ятнадцяти років, переважно у сфері back-end. Починаючи свій шлях в програмуванні, мав іншу вищу освіту і в мене не було змоги попрацювати та оцінити C++ в рамках класичної навчальної програми. Тому цей огляд являє собою точку зору аматора, для якого хоббі стало професією; хто вивчав програмування самостійно і починав це вивчення з мови високого рівня а не навпаки (у моєму випадку - PHP)
|
||||
|
||||
## Передмова
|
||||
|
||||
Так сталось, що у сферу Веб потратив через особистий інтерес до її потенціалу на ті часи, а домінантною мовою в мережі - була PHP, тому і обрав саме її. Так і вивчав: спочатку різні CMS, потім CMF, почав створювати власні самописи, потім бібліотеки.
|
||||
|
||||
Звісно, в процесі довелось працювати і з суміжними мовами та їх технологіями (HTML, CSS, JS), так і альтернативи back-end, такі як Python. Оскільки вже більше 10 років користуюсь Linux, час від часу вносив невеличкі контрибуції в проєкти на C/C++, відповідно працював з інструментами компіляції, встановлюючи останні версії таких програм. Також в мене був деякий досвід програмування контролерів Arduino, наприклад обробка сигналів різноманітних датчиків, взаємодія з GSM та інше.
|
||||
|
||||
Отже заочно з мовами групи C знайомий, оскільки постійно натикався в роботі. Але мені ніколи не доводилось писати на ній щось нове, наприклад з використанням графічного інтерфейсу GTK або для роботи з мережевими інструментами. Одного разу, я знайшов собі таку задачу на вільний час - браузер для протоколу Gemini. Спочатку, написав прототип на вже знайомій мові PHP, з використанням бібліотек PHP-CPP та PHP-GTK3, але виявив що в останній - багато методів GTK не реалізовані, тому витрачав багато часу на доробку бібліотеки, а не створення самої програми. До того ж на момент роботи, актуальною версією була GTK 4 і тут потрібно було або писати бібліотеку з нуля, або створити для браузера окрему гілку і писати його тією мовою, якою написаний сам фреймворк. Власне так і почався мій фундаментальний квест у світ C++
|
||||
|
||||
## Перехід з PHP
|
||||
|
||||
PHP має C-подібний синтаксис, а об'єктне програмування - вже давно стало мейнстрім стандартом а не опцією, тому особисто мій перехід на C++ був відносно легким. Можна швидко переписати скелет програми, при цьому трохи видозмінивши оголошення класів, додавши їх до заголовкових файлів.
|
||||
|
||||
Утім, присутня й кардинальна відмінність у моделі роботи з пам'яттю, яка може змусити переписати з нуля майже всю програму.
|
||||
|
||||
## Вказівники і посилання
|
||||
|
||||
Деякі складнощі можуть виникнути з "новими" типами даних: зокрема вказівниками та посиланнями. Це швидко стає зрозумілим, як тільки отримаєте segmentation fault і почнете копати причину вже на реально написаній програмі а не теорії.
|
||||
|
||||
Оскільки C++ не використовує рантайм, як PHP, Python чи Go - написати програму без прямого звернення до пам'яті ви просто не зможете, а отже - доведеться трохи розібратись з тим, як для кожного з типів даних програма буде виділяти пам'ять та звільняти її.
|
||||
|
||||
Що добре - в мережі просто навалом як документації, так і авторських уроків, зокрема відео курсів українською мовою. Тому зупинятись не будемо, в цілому в мене тема зайняла пару днів поки засвоїлась практично. Трохи ускладнюють тему так звані "розумні вказівники", які потягнуть за собою шаблони функцій та ще купу всього. Плюс вони мають різні реалізації в різних бібліотеках, але я вивчав їх послідовно - коли вирішував окремі проблеми вже потім, зрозумівши основи.
|
||||
|
||||
Від себе тільки додам, що вказівник та посилання - це по суті "ярлик" на певну частину пам'яті, а не копія його об'єкту. Оскільки ваша програма не створює копії об'єктів кожного разу при їх зверненні, це і робить C/C++ таким швидким. З іншого боку, доступ до спільних ресурсів знижує стабільність бо є ризик перезаписати одні і ті само дані в різних частинах програми. Цим і займаються "розумні вказівники" тож по суті - все просто!
|
||||
|
||||
## Конструкції if та switch
|
||||
|
||||
Стосовно конструкцій if - в C++ всі вони повинні оперувати з типами true / false. В принципі, те само й для інших мов, просто там корекція типу відбувається автоматично, а тут неправильний тип викличе помилку компіляції. Я завжди намагаюсь оголошувати типи даних в PHP, тому в C++ це нарешті для мене велика перевага, а ніж незручність.
|
||||
|
||||
Також є певні відмінності при роботі зі switch - тут ви не можете просто закинути в умову будь що, а повинні створити або число або попередньо оголошений enum (також є числом). Не зважаючи на те, що С++ синтаксично схожа на PHP, все таки це "найбільш низькорівнева мова високорівневих" (с)
|
||||
|
||||
## Робота з типами даних
|
||||
|
||||
На від міну від C та їй подібних мов, C++ має розширений інструментарій для роботи з висхідними і низхідними операціями перетворення даних: const_cast, static_cast, dynamic_cast, reinterpret_cast. На перший погляд, додаткові конструкції заплутують на етапі вивчення та ускладнюють читабельність коду - потім, але на практиці, дозволяють регулювати співвідношення продуктивності та стабільності програми. Характерні для C перетворення типу (MyClass*) не бажані, оскільки є найменш стабільними, у чому особисто я переконався доволі швидко :)
|
||||
|
||||
## Перезавантаження функцій
|
||||
|
||||
Якось рефакторив код і випадково помітив, що у моєму класі лишилось два однойменні методи, при чому а ні аналізатор, а ні компілятор - не видавали помилок:
|
||||
|
||||
``` cpp
|
||||
void MyClass::method1();
|
||||
void MyClass::method1(int x, int y);
|
||||
```
|
||||
|
||||
Наткнувся випадково і швиденько видалив, щоб не соромитись. Але згодом зрозумів, що це є фіча, якої мені давно не вистачало в інших мовах! Таким чином, можна створити багато методів з різним API, а не оголошувати значення атрибутів за замовчуванням та не придумувати якісь ініціальні дані для обов'язкових атрибутів. Тут є своя специфіка, але в цілому - дуже зручна опція!
|
||||
|
||||
## Рядкові типи даних
|
||||
|
||||
Де я спочатку застряг - так це на рядках. По-перше їх можна оголосити (і зберігати у пам'яті) різними способами:
|
||||
|
||||
``` cpp
|
||||
char str[] = "C++";
|
||||
char str[4] = {'C','+','+','\0'};
|
||||
const char* str = "C++";
|
||||
std::string str = "C++";
|
||||
// ...
|
||||
```
|
||||
|
||||
По-друге, якщо ви працюєте з сирим типом char, вам доведеться постійно працювати з ними як з масивом і відповідно - його довжиною, наприклад ви не зможете просто передати змінні до макросів через sprintf, для цього вам знадобиться також знати кількість символів рядка, спочатку створивши його буфер (а також збільшувати його за необхідності).
|
||||
|
||||
На щастя, в C++ багато попередньо реалізованих класів, що полегшують таку роботу. Зокрема, в своїй програмі на GTK, я оголошую рядки як об'єкти класів Glib::ustring (для STL є схожий метод) та працюю з ними так само, як в PHP:
|
||||
|
||||
``` cpp
|
||||
using Glib::ustring; // namespace для виклику sprintf
|
||||
|
||||
sprintf(
|
||||
"%s and %d",
|
||||
"substring",
|
||||
1
|
||||
);
|
||||
```
|
||||
|
||||
Тим не менше, все одно доведеться розібратись з примітивними типами даних, оскільки без цього ви просто не зможете зрозуміти як працювати з пам'яттю, не викликаючи її помилок роботи.
|
||||
|
||||
## Масиви
|
||||
|
||||
В C++ можна так само працювати зі статичними масивами, як і в інших мовах, але в більшості випадків, масиви використовуються саме для операцій з динамічними даними. Якщо в PHP можна просто накидати нові елементи масиву "в процесі роботи" програми, то в C++ потрібно спочатку подбати про виділення пам'яті, щоб випадково не зчитати взагалі дані іншої програми, коли відбувся вихід за рамки оголошеного діапазону.
|
||||
|
||||
Це непорозуміння може виникнути тому, що PHP являє собою препроцесор, по суті заголовковий файл, де вся робота з динамічними даними виконується на етапі інтерпретації до запуску програми середовищем (runtime) якого в C++ просто немає. Тому таку роботу повинен виконати програміст - або на рівні препроцесору або виділяти пам'ять безпосередньо під час роботи програми.
|
||||
|
||||
Коли стомитесь від ручного керування, дуже скоро віднайдете для себе "вектори" стандартної бібліотеки, які по суті являють собою допоміжні класи для роботи з динамічними масивами, так само як і відповідні класи для рядків - автоматизують рутинні задачі і роблять це безпечно (хоч і за рахунок зменшення швидкодії):
|
||||
|
||||
``` cpp
|
||||
std::vector<int> numbers;
|
||||
|
||||
numbers.push_back(10); // додати 10 в кінець масиву
|
||||
```
|
||||
|
||||
Вектори будуть створювати новий простір (capacity) для ваших даних автоматично, тому не потрібно цим займатись самостійно. У класу векторів є багато інших методів, якими також можна задати початковий розмір простору або алгоритм перезапису, щоб збільшити швидкодію програми за рахунок виділення більшого об'єму пам'яті заздалегідь. Тому всі ці на перший погляд "складнощі" стають перевагами тоді, коли ви розберетесь в принципах їх роботи.
|
||||
|
||||
## Класи
|
||||
|
||||
Якщо в PHP класи - це такі собі структурні одиниці, де описані всі їх компоненти то в C++ класи розділені на файли для компіляції (.cpp) та окремі заголовкові файли (.h, .hpp), що описують структуру та забезпечують попередню логіку препроцесора. По суті, функціональність програми ділиться на таку, що виконується препроцесором до компіляції і ту, яка виконується після такої.
|
||||
|
||||
### Простори імен
|
||||
|
||||
Починаючи зі стандарту C++17, працювати з класами у заголовкових файлах доволі інтуїтивно: можна використовувати як інлайн, так і вкладені конструкції, скорочуючи об'єм коду через using:
|
||||
|
||||
``` cpp
|
||||
namespace myNamespace
|
||||
{
|
||||
class myClass;
|
||||
}
|
||||
|
||||
using myNamespace::myClass;
|
||||
```
|
||||
|
||||
Щодо синтаксису файлів для компіляції - мені не дуже сподобався формат оголошення членів класу, на рівні написання їх у спільному просторі файлу замість розміщення у фігурних дужках цього класу:
|
||||
|
||||
``` cpp
|
||||
void myClass::methodOne() {}
|
||||
void myClass::methodTwo() {}
|
||||
// ...
|
||||
```
|
||||
|
||||
Звісно, я можу користуватись using для скорочення, але так як це виглядає класично - являє собою суцільні дублі назв одного й того ж класу. Поточний формат мабуть успадкував цей стиль від процедурного підходу C, або ж так зроблено для зворотної сумісності компілятора - іншого логічного пояснення не бачу.
|
||||
|
||||
Складається враження, що сучасний підхід ООП з його практиками (зокрема, 1 клас - 1 файл) відбувся вже після того, як сформувалась мова C++, тут відчувається ретро.
|
||||
|
||||
### Ключове слово this
|
||||
|
||||
Після роботи з іншими мовами ООП, може збивати з толку відсутність ключового слова this, хоча воно доступне, але на практиці майже не використовується. Може виникнути ситуація, коли ви захочете передати однойменний аргумент функції:
|
||||
|
||||
``` cpp
|
||||
class MyClass
|
||||
{
|
||||
int argument;
|
||||
|
||||
void Method(int argument);
|
||||
};
|
||||
|
||||
void MyClass::Method(int argument)
|
||||
{
|
||||
argument = argument; // :)
|
||||
}
|
||||
```
|
||||
|
||||
Звісно, ви можете зробити так:
|
||||
|
||||
``` cpp
|
||||
void MyClass::Method(int argument)
|
||||
{
|
||||
this->argument = argument;
|
||||
}
|
||||
```
|
||||
|
||||
Але такий спосіб мені здається не надійним і його робота може залежати від настрою певного компілятора, тому потрібно вигадувати якісь нові назви для однойменних змінних, у той час як стандартом C++ не рекомендується використання нижніх підкреслень на початку назви (через зарезервовані імена), а підкреслення в кінці - як правило означає назву приватного члена класу.
|
||||
|
||||
Так як this чомусь не використовується цією мовою іншими програмістами, я це питання вирішую вбиваючи для себе двох зайців: і створюю константу (класично - у верхньому реєстрі) і пришвидшую роботу з пам'яттю через роботу з посиланням:
|
||||
|
||||
``` cpp
|
||||
void MyClass::Method(const int & ARGUMENT)
|
||||
{
|
||||
argument = ARGUMENT;
|
||||
}
|
||||
```
|
||||
|
||||
### Інкапсуляція
|
||||
|
||||
Так як фішкою C++ є саме ООП, зі всіма перевагами використання класів - зокрема інкапсуляції, не так давно я стикнувся з неприємним нюансом при роботі з посиланнями, раз вже згадав про них у попередньому розділі.
|
||||
|
||||
Наприклад в мене є клас, що має певну закриту (private) структуру. Щоб пришвидшити роботу програми, я хотів би передавати її вміст за посиланням (через публічний getter) замість створення окремої копії об'єкта. Але оскільки я надаю зовнішньому компоненту посилання на "приватний" блок пам'яті, а також тип даних, який там зберігається, цей компонент може змінити дані, що розташовані в закритій структурі мого класу.
|
||||
|
||||
Тут також є дуже спірні моменти з рівнем доступа friend, що ламає звичну інкапсуляцію. Це звісно не проблема, якщо ви самі пишете код програми або маєте програмний регламент, але таким чином немає жодних гарантій, що якийсь інший блок програми не перепише приватні дані.
|
||||
|
||||
Таким чином, посилання або вказівники на дані приватних структур, які я віддаю на зовні, відкривають їх, і мені варто одразу зробити такі структури публічними, що по суті робить їх не класом а struct.
|
||||
|
||||
## Заголовкові файли
|
||||
|
||||
Для того, хто ніколи не зустрічав таких файлів (.h, .hpp) у сучасних мовах вищого рівня, постане логічне питання: навіщо вони взагалі потрібні. Наскільки мені вдалось усвідомити для себе, оскільки в C++ все повинне мати оголошений тип (для відповідного виділення пам'яті) це свого роду мета-інформація для зовнішнього об'єкту, без підключення безпосередньо його логіки (.cpp).
|
||||
|
||||
Наприклад, коли потрібно використати певний тип даних з іншого файлу, що підключається - компілятор нічого не знає про цей тип, адже його не було оголошено раніше у поточному файлі. Саме тому, через заголовковий файл, передається структура доданого об'єкту і те, скільки і яким чином потрібно виділити під цей тип даних пам'яті.
|
||||
|
||||
З іншого боку, я все ще не дуже зрозумів, як саме працює варіант у прикладі нижче і чому взагалі є така можливість оголосити тип даних у поточному файлі без підключення повних заголовків відповідних класів:
|
||||
|
||||
``` hpp
|
||||
// оголошення типів даних без підключення Class1, Class2, Class3 через include
|
||||
class Class1;
|
||||
class Class2;
|
||||
class Class3;
|
||||
|
||||
void someMethod(Class1, Class2, Class3); // це не викличе помилки компіляції
|
||||
```
|
||||
|
||||
В заголовкових файлах іноді прописують допоміжну логіку для автоматичної "підстановки" даних до компіляції, наприклад - макроси або певні функції, які не потрібні безпосередньо під час виконання програми. Використання макросів, ніби як не рекомендоване в мові C++ тому я поки що не використовую в заголовках динаміку, але трішки експериментую з "пресетами", щоб не писати наприклад тексти та стандартні значення чисел в коді. Також, в цих файлах можуть бути оголошені стандартні визначення для аргументів функцій:
|
||||
|
||||
``` hpp
|
||||
void someMethod(int arg1 = 1, bool arg2 = true);
|
||||
```
|
||||
|
||||
Мені це здається не дуже зручним, оскільки стандартні значення не можна вказати у файлах cpp і я постійно про них забуваю. Доводиться постійно тримати в голові два різних файли, з різним синтаксисом, які по суті являються компонентами одного майбутнього об'єкта.
|
||||
|
||||
В іншому - по цій темі нічого складного немає, оскільки такі файли використовуються препроцесором, швидко приходить розуміння що саме в них писати, таким чином значно розвантажуючи основні файли для компіляції. Це простіше зрозуміти, якщо сприймати заголовки у якості "спільної" інформації для всієї програми, свого роду "абстракції". Структури, оголошені в заголовках, ще називають "прототипами".
|
||||
|
||||
Додам ще декілька слів стосовно мого вибору назви розширення для заголовків. Адже можна назвати файл .h, а можна .hpp. Особисто я користуюсь в проєкті C++ саме .hpp тому що розробники, які читатимуть код потім, можуть сприйняти .h як сумісний формат також для компіляції C. Це моя суто теоретична логіка.
|
||||
|
||||
## Багатофайлові проєкти
|
||||
|
||||
Типовий для PHP include має аналогічний спосіб підключення файлів в C++ через #include який по суті копіює код донора в цільовий файл.
|
||||
|
||||
Якщо потрібно використати include_once, то в C для цього використовується директива #pragma once. Можна також користуватись перевіркою визначення констант через #ifdef.
|
||||
|
||||
* include C++ є аналогом require в PHP, оскільки виконується на етапі передкомпіляції
|
||||
|
||||
Оскільки в PHP я користуюсь пакетним менеджером та засобами autoload, мені здалось трішки не зручним роботи це знову вручну. Більше того, потрібно в ідеалі спроєктувати програму так, щоб не користуватись #pragma once взагалі, оскільки це зайва робота для процесору на етапі збірки, яка виконується постійно.
|
||||
|
||||
## Пакетний менеджер
|
||||
|
||||
Поки що, мені не доводилось користуватись такими бібліотеками, яких немає в репозиторії мого дистрибутиву. Звісно, розумію що одного разу такий момент настане, тим паче, що я звик виносити окремі функції програми на рівень маленьких бібліотек і працювати з ними через пакетний менеджер, замість використання моделей.
|
||||
|
||||
В принципі, такі пакетні менеджери для C++ є, наприклад Conan (https://conan.io). Але мене трохи засмучує, що немає якось єдиного хабу по типу Composer/Packagist для PHP. В цьому плані, звісно дуже виграє Rust з його пакетним менеджером Cargo. Хотілось би подібний набір для C++ з коробки, але все таки це мова, яка сформована спільнотою і має трохи іншу, свого роду анархічну парадигму в своїй основі, яка не прив'язує вас до конкретного рішення і дає повну свободу дій.
|
||||
|
||||
Коли дійдуть руки до організації сторонніх бібліотек, в першу чергу, хочу спробувати варіант з git submodule. Це не зовсім пакетний менеджер, але у даного рішення є таке поняття як "теги", з яких формуються безпосередньо версії, git також перед-встановлено на більшості систем тих, хто займається збіркою і не доведеться вимагати від користувача додаткових рухів. Тому наразі це рішення для мене виглядає найбільш привабливим, перш за все - з точки зору універсальності.
|
||||
|
||||
## Автоматична збірка
|
||||
|
||||
До цього поки що не дійшов, але історія обіцяє бути веселою. Не кажучи про мобільні платформи, наразі я розробляю та запускаю програму на Debian 12, але досі не можу зробити цього на Ubuntu 24.04 через конфлікти залежностей, жорстко прописані у Makefile. Окрім make існує чимало альтернативних рішень, але використовуючи їх для себе, мені також доведеться подбати і про класичний спосіб в README.
|
||||
|
||||
Вже заздрю користувачам більш сучасних екосистем Rust та Electron :)
|
||||
|
||||
## IDE
|
||||
|
||||
Однією з помилок, якої припускався, коли працював з C++ до того як взявся за справу фундаментально, була відсутність правильно налаштованого середовища для розробки. Раніше я користувався продуктами JetBrains, але потім перейшов на VSCodium, де середовище під кожну мову потрібно збирати самому.
|
||||
|
||||
Тема IDE потягне на окремий матеріал, але у будь якому випадку, перш ніж почати вивчення і практичну роботу, важливо одразу користуватись відповідними інструментами, що полегшують інтерпретацію та аналіз коду локально, до компіляції всієї програми. Інакше ви ризикуєте пропустити вивчення мови тільки по тій причині, що вона була погано інтегрована!
|
||||
|
||||
### Аналізатор коду
|
||||
|
||||
Тут, окрім вбудованої підсвітки синтаксису, важливо також довстановити аналізатор коду, який буде здійснювати попередню компіляцію і підсвітку типів даних, а також додасть підтримку вбудованої документації та авто-доповнень, що особливо зручно при роботі з наслідуванням класів.
|
||||
|
||||
Особисто я користуюсь плагіном clangd і навіть не уявляю, як раніше редагував і збирав програми без його функцій!
|
||||
|
||||
Також важливо не тільки встановити плагін, але й правильно налаштувати залежності проєкту (у даному плагіні це clangd.fallbackFlags), які використовуються в лінкері - без них, встановлений аналізатор просто не розкриє свій потенціал.
|
||||
|
||||
=> https://github.com/clangd/vscode-clangd Офіційний репозиторій vscode-clangd
|
||||
|
||||
### Дебагер
|
||||
|
||||
Іншим рішенням, без якого не обійтись - це звичайно дебагер для відлагодження коду, у моєму випадку - codelldb
|
||||
|
||||
=> https://github.com/vadimcn/codelldb Офіційний репозиторій codelldb
|
||||
|
||||
### Авто-доповнення
|
||||
|
||||
Є думки поставити плагін ШІ, наприклад Copilot, але поки що надаю перевагу Chat GPT і Claude 3 Haiku в браузері.
|
||||
|
||||
## Висновки
|
||||
|
||||
Безумовно, C++ є дуже потужним інструментом, що відкриває можливості, які ви не отримаєте від подібних мов на рантаймі. З іншого боку, не завжди такі можливості можуть бути виправдані по часовим витратам, які потрібні на забезпечення їх стабільності.
|
||||
|
||||
Це можна порівняти з ручною коробкою передач в автомобілі: у певних моментах вона виручає, але у більшості випадків ви будете робити зайві рухи, стоячи десь у заторі тільки витрачаючи зайве пальне (так само як і розробляти певні програми на потоці).
|
||||
|
||||
В плані мови для загального розвитку, як хоббі, C++ нагадує мені гру з відкритим світом, де можна робити все, що завгодно і як завгодно. Ця гра має великий всесвіт, який наврят може бути колись вивчений, навіть якщо ви працюєте з плюсами все життя. Тут немає основного сюжету чи сценарію, це динамічне середовище, яке об'єднує тільки стандарт, що оновлюється кожні три роки.
|
||||
|
||||
Подібно як з PHP - мало розуміти мову, потрібно знати певний фреймворк, патерни та інструменти, і вже тоді можна робити якісь практичні речі ефективно. Так само і тут: шлях, яким ви підете вірогідно залежатиме від бібліотеки, яку почнете вивчати, наприклад у моєму випадку - це GTK, тому я вже мабуть краще знаю API цієї групи бібліотек, ніж STL.
|
||||
|
||||
C++ це основа, свого роду класика. Я не міг пройти повз. Особисто, вивчаю її у вільний час просто тому, що мені вже не цікаво розробляти програми на тих мовах, які я знаю добре. А розуміння того, як написаний їх інтерпретатор допомагає мені також краще розуміти принцип роботи таких програм, вносити контрибуції в їх рушій, та експериментувати з новими технологіями, які працюють на пристроях з обмеженою пам'яттю або вимагають максимальної швидкодії.
|
||||
103
public/uk/first-steps-in-gtk.gmi
Normal file
103
public/uk/first-steps-in-gtk.gmi
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
# Мої перші кроки в GTK
|
||||
|
||||
## Передмова
|
||||
|
||||
Не так давно захотілось зробити простенький браузер для протоколу Gemini. Зокрема - додати детекцію Geo-IP капсул, власний пошук на базі Manticore та інтегрувати екосистему Yggdrasil.
|
||||
Для обраного протоколу задача виглядала тривіальною, залишалось обрати графічний фреймворк і накидати туди крутих функцій.
|
||||
|
||||
Я постійний користувач Linux, вибір був між Qt та GTK. З Qt вже поверхнево знайомий, в рамках одного з проєктів, що довелось апгрейдити і разом з тим оновлювати залежності API (досі приходить спам після обов'язкової реєстрації для завантаження останньої SDK)
|
||||
Але оскільки завжди був користувачем середовища GNOME, все таки пішов стежкою GNU і вирішив глянути що там і як робиться на практиці.
|
||||
|
||||
Забігаючи вперед, скажу що займався професійно виключно веб розробкою, добре знаю суміжні мови, патерни і фреймворки. Але це була фактично моя перша десктоп програма, яку захотілось написати з нуля.
|
||||
Заради цікавості вбив у пошук знайому для себе комбінацію "PHP-GTK" і щось там побачив! Ну, а оскільки вже чимало часу провів з PHP, то написати браузер цією мовою було доволі простою задачею - в запасі вже було з десяток власних бібліотек, лишалось їх тільки натягнути на віконний API і все.
|
||||
|
||||
Отже, знайшов пару прикладів, написав простенький код виклику вікна - працює, значить працюватиме й інше!
|
||||
|
||||
## Інформація в мережі
|
||||
|
||||
Перше з чим зіткнувся, на відміну від Qt, PHP/JS та інших поп-технологій, пошукові видачі по GTK - порівняно порожні або посилаються на якісь старі мануали по другій версії.
|
||||
|
||||
Звісно є офіційна документація, але без розуміння загальної картини.. взагалі складно.. як, що, до чого. На ютубі теж тотальний кошмар, але частково є англомовний контент в основному по двійці, якості не краще. Краще не дивитись. Довелось пробиратись через тернові хащі розуміння самому. Вирішив нарешті задати дільне питання Chat GPT і Haiku, останній до речі доволі точно і лаконічно генерує приклади на Python, C та C++
|
||||
|
||||
## Документація
|
||||
|
||||
В принципі, вона є але доволі скупа і потребує деякого рівня для входу. Але так якщо писати програму по інструкціям ШІ та паралельно читати документацію по кожному методу і його типам то по-трохи можна в'їхати що до чого.
|
||||
|
||||
## Поняття Widget
|
||||
|
||||
В якийсь момент, почав розуміти що є деякі класи, з яких подібно блокам конструктора, складається вікно і всі його елементи. Ці класи потрібно зібрати до купи в рамках іншого класу-віджету у потрібному порядку і вкладеності: копки, поля та інше - формуючи в результаті вікно і заголовок (який тут теж є віджетом).
|
||||
|
||||
Згодом, працюючи безпосередньо з компонуванням, стало відомо про такий інструмент як Glade, який дозволяє робити те само не в коді а через UI (як Unity для ігор) а проєкт експортувати - в XML, який в свою чергу, потім можна імпортувати в об'єкти - вже засобами класу Builder.
|
||||
|
||||
В принципі, використовувати Glade чи ні - справа вподобань. Особисто мені не подобається UI та XML як явище в ООП, але офіційного аналогу JSON не знайшов, тому й далі описую віджети об'єктами в коді програми. Варто зазначити, що для GTK 4, Glade вже не використовується, а на його офіційному сайті висить заглушка nginx. Тут на зміну для четвірки приходить нова і мабуть єдина, неофіційна програма і новий формат проєкту файлів - Cambalache.
|
||||
|
||||
## Ієрархія і наслідування
|
||||
|
||||
Через певний час роботи, виявиться що деяких методів в прикладах, які описує ШІ немає в документації класу і це не помилка! Як виявляється, на сторінці кожного віджету можна побачити дерево наслідування, і воно там проілюстроване не спроста.
|
||||
|
||||
Таким чином, в пошуках певної функції для тюнінгу програми, вже можна читати не тільки документацію робочого класу, але й обов'язково його батьківського елементу - де виявляється ціла купа нових методів про які на сторінці самого методу не згадується окрім клікабельної мапи наслідування. Це була суто моя, користувацька неуважність і як наслідок самостійна реалізація функціональності яка вже була давно доступна, просто з інструментами які знаходяться рівнем вище у батьківських класах та групах об'єктів.
|
||||
|
||||
Якщо пишете програму на C, то ймовірно це буде простіше, оскільки компілятор підсвітить та авто-доповнить семантику. Але в моєму випадку - був шлях пробивного першопрохідця на PHP, який ще й писав порт на PHP-CPP мабуть довше ніж сам браузер.
|
||||
|
||||
По цій темі можна ще додати наступне. Якщо ви пишете першу програму GTK на C++, то ймовірно вже віднайшли і користуєтесь враппером gtkmm (і його сателітами - glibmm і giomm) - така собі абстракція, яка спростить код але добряче заплутає в офіційній документації для C через свою абстрагованість. Частина API в gtkmm досі не реалізована. Також офіційні класи GTK 4, на відміну від GTK 3, вже оголошені як final, тобто не можуть наслідуватись і передбачають або агрегацію або композицію. Разом з тим, gtkmm все ще дозволяє наслідування (подібно Qt) і тут звісно теж не дуже зрозуміло як краще проєктувати програму згідно стандартам і що на gtkmm чекатиме завтра. Але бібліотека безумовно зручна, дійсно зменшує об'єм коду в рази три.
|
||||
|
||||
Все таки мені здається оптимальним писати першу програму GTK на С а не C++, чи наприклад Rust. C, не зважаючи на потенційно більшу кількість коду і відсутність ООП, на мою думку, буде простішим шляхом для початківця, зокрема у вивченні того як влаштована ієрархія фреймворку, події, використання пам'яті. І вже тільки потім варто переходити на абстрактний рівень вище. Для себе все ще не визначився бо все життя провів в ООП, і вже не уявляю без цього програму більшу за "hello world"
|
||||
|
||||
## Типи даних і допоміжні функції
|
||||
|
||||
Низькорівневі бібліотеки Gio/Glib містять чимало зручних функцій для роботи з кодуванням, розміткою, сокетами і взагалі все що потрібно для роботи з контентом. Багато з них наслідують STL. Коли я вперше відкрив для себе розділ функцій то чомусь мені згадалось різноманіття препроцесору розмітки PHP - де є все для роботи з веб, а у веб зараз є все.
|
||||
|
||||
Таким чином, майже не використовую STL бо майже на кожну функцію і тип даних, в середовищі GTK для них є розширена і адаптована реалізація.
|
||||
|
||||
## Робота з контентом
|
||||
|
||||
Якщо говорити про вивід даних в контексті браузеру, який у моєму випадку має відображати простий gemtext з клікабельними посиланнями, починається деякий дисонанс після роботи з JS/HTML.
|
||||
|
||||
По-перше в GTK є тільки два відомих мені віджети для тексту - Label і TextView
|
||||
|
||||
Label - це по суті блок для невеликого тексту, який може підтримувати розмітку або звичайний текст. Розмітка при цьому використовує формат Pango, тобто це такий собі мінімальний варіант HTML з декількома тегами і класами, що використовується для інших, специфічних для стаціонарних програм цілей. Поле Label не розраховане на великий об'єм даних, тому як і варто очікувати мігрантам з HTML - сенс його однозначний - невеличкий опис до якогось блоку і все. Текст на 100Кб відправить вашу програму в роздуми на 10 секунд, особливо якщо спробуєте відформатувати Layout своїм способом, наприклад перерахувати word-wrap чи відмалювати інакше шрифти перед додаванням у віджет.
|
||||
|
||||
Тим не менше, усі дороги і поради "бувалих" ведуть саме на Label, але якщо залізти у вихідний код інших, швидких GTK браузерів то побачимо, що часто використовується багаторядкове текстове поле вводу TextView. По суті, це аналог поля textarea, в якому достатньо сховати курсор засобами CSS (наприклад, через caret-color: transparent) та перевести віджет в режим readonly (через set_editable).
|
||||
Цей віджет так само підтримує розмітку, події, користувацькі теги а також буфер, в який можна складати і відмальовувати невеликий текст по мірі прокрутки контенту, як багато хто і робить що і являє собою розгадку швидкодії рендерингу великих документів.
|
||||
|
||||
Говорячи про прокрутку. Ще не знаю як в GTK 4, але в GTK 3 віджет, який не підтримує засоби скролу, потрібно додати у відповідний контейнер Viewport. Інакше ви довго не будете розуміти чому ваш текст сам по собі відскролюється на верх, наприклад при перемиканні табів Label віджету Notebook. Так само в іншому, очевидно вектор спрощення торкається не тільки візуальної але і внутрішньої частини GTK - розробник повинен сам реалізувати потрібні йому набори, навіть якщо вони здаються тривіальними і такими, що здавалось би, мають бути з коробки.
|
||||
|
||||
Щодо CSS - тут від нього тільки три літери, і мабуть три властивості в залежності від двох тегів, які оберете :)
|
||||
|
||||
Є віджет для картинки (Picture) і є для більш простої піктограми, наприклад для віджету кнопки (Image) якщо треба більше - пишіть самі. Мінімалізм.
|
||||
|
||||
## Робота з діями
|
||||
|
||||
Фреймворк базується на системі подій, тому, хто добре знайомий з JavaScript / Node.js, буде просто розібратись.
|
||||
Кожен віджет здатен оголошувати власні Action, ActionGroup, а також звертатись до глобальних рівнів вікна (win) та застосунку (app)
|
||||
|
||||
Взагалі тема велика і було б добре написати про неї окремо, але нагадаю, особливо бекендерам: на систему дій потрібно звернути увагу в першу чергу і не писати передачу викликів методами класів, ін'єкцією залежностей і т.д., як робив це я спочатку.
|
||||
|
||||
## Спільнота
|
||||
|
||||
В GNU спілньота живе десь в чистилищах своїх гітлабів та інших екзотичних місцях. На гітхабі звісно ваша присутність не допоможе, доведеться по всім баг-репортам реєструватись на окремих сайтах. А для підтримки користуватись форумом. В принципі 2-3 користувача час від часу відповідають (схоже на співробітників фундації) але особисто мені це не зовсім зручно, в порівнянні з системою Issues та PR на GitHub.
|
||||
|
||||
Для себе, в навчанні, й досі користуюсь ШІ, потім читаю документацію, пишу код, і так по колу. Пошук Google тут видає аж нічого цікавого. В принципі форум читати не дуже інформативно бо старі теми там закриваються і коментувати туди вже не можна.
|
||||
|
||||
## Висновки
|
||||
|
||||
Мені чимось подобається графічне середовище GNOME: можливо своєю простотою та однорідністю застосунків, що схоже за філософією на MacOS, користувачем і фаном якої я був довгий час. Й досі, використовую GOME на машині iMac (оскільки для розробки користуюсь Linux)
|
||||
|
||||
GTK має більш інтуїтивний, матеріальний інтерфейс, в той час як Qt та різноманітні JS/Electron чомусь асоціюються з пластиком, де кожна програма має різні властивості, таймінги відгуку, що не зручно коли фокусуєшся на роботі.
|
||||
|
||||
Звісно з трійкою все пішло мобільним шляхом, робочий стіл став пустим місцем, а програми такі прості що виконують буквально одну функцію. Все що більш менш в побуті - на Qt.
|
||||
|
||||
Власне кажучи, буду намагатись й надалі в'їхати в тему GTK, а коли все вляжеться і засвоїться то може буде сенс написати якийсь навчальний матеріал по одній конкретній темі. Ну а зараз, думаю краще поділитись тим що маю - першим враженням з точки зору розробника, і як бачу GTK під капотом в цілому після декількох місяців користування.
|
||||
|
||||
## Щодо браузера
|
||||
|
||||
Наразі в нього утворилось дві гілки:
|
||||
|
||||
=> https://github.com/YGGverse/Yoda/tree/PHP-GTK3 PHP-GTK3
|
||||
|
||||
* більш функціональна але ймовірно вже архівна версія, оскільки писати на GTK 3 не бачу сенсу а вкладатись в контрибуцію бібліотеки Zend / GTK 4 зараз не цікаво. По суті включає базові функції - відкриває файли, протоколи nex та gemini. Останньою фічею була авторизація сертифікатами TLS (коди групи 60), тому якщо комусь цікаво - може поколупатись в робочих прикладах багатопоточної реалізації PHP/GTK так і обробки протоколу Gemini зокрема.
|
||||
|
||||
|
||||
=> https://github.com/YGGverse/Yoda/tree/CPP-GTK4 CPP-GTK4
|
||||
|
||||
* остання версія, стан чернетки, в якій я досі не визначився з патерном. Можливо взагалі переключусь на C або відкрию нову гілку на Rust, який мене давно цікавить своїм пакетним менеджером.
|
||||
157
public/uk/flatpak-bundle-build.gmi
Normal file
157
public/uk/flatpak-bundle-build.gmi
Normal file
|
|
@ -0,0 +1,157 @@
|
|||
# Створення пакунку Flatpak
|
||||
|
||||
Маю декілька улюблених програм, зокрема - пірингова платформа мікроблогів twister p2p та key/value база даних у блокчейн - KevaCoin, які доволі важко збираються на сучасних системах, тим не менше потребують нових юзерів для існування їх пірингових мереж. Раніше, робив для них локальні збірки у бінарному форматі та пакунках `deb`, але з часом вони втрачали свою актуальність через залежність від батьківського середовища. Тому врешті зібрався часом та створив два пакунки Flatpak, які обіцяють не старіти з часом, щонайменше, в осяжній перспективі.
|
||||
|
||||
Тема Flatpak - не нова, у цьому матеріалі я не стану вдаватись в детальні гайди і архітектуру, але поділюсь власним, першим досвідом роботи з цією системою пакунків, наведу декілька прикладів роботи а також спробою публікації на хостингу Flathub. Особисто мені не вистачало такого коротенького гайду, а попередні спроби перечитати документацію від і до, закінчувались нудьгою і відкладаннями на потім у моментах, які мені були одразу не очевидними без практики.
|
||||
|
||||
## Платформи
|
||||
|
||||
Екосистема Flatpak влаштована довкола так званих "рантаймів" або платформ - тобто програмних комплексів або середовищ, які характерні для певної операційної системи, на якій і засобами якої планується збірка програми:
|
||||
=> https://docs.flatpak.org/en/latest/available-runtimes.html
|
||||
|
||||
Основною платформою є Freedesktop:
|
||||
=> https://gitlab.com/freedesktop-sdk/freedesktop-sdk
|
||||
можна сказати, це такий собі голий Linux, який підійде для програм, які не потребують характерних залежностей GTK чи Qt. Для останніх, існують окремі платформи, які по суті розширюють Freedesktop:
|
||||
=> https://gitlab.gnome.org/GNOME/gnome-build-meta GNOME
|
||||
=> https://invent.kde.org/packaging/flatpak-kde-runtime KDE
|
||||
|
||||
Для програм, які використовуватимуть дані фреймворки, специфічна платформа не обов'язкова, ви можете зібрати всі необхідні залежності з початкового коду для Freedesktop, якщо у вас звісно є таке бажання.
|
||||
|
||||
Кожна з платформ має версію релізу, і оновлюється як мені здається раз на рік, тому важливо актуалізовувати вашу програму, якщо ви не бажаєте вимагати від юзера ставити додаткову "операційну систему" лише задля запуску однієї вашої програми.
|
||||
|
||||
## Інкапсуляція
|
||||
|
||||
У контексті Flatpak, мабуть, правильніше використовувати поняття "пісочниці" або Sandbox:
|
||||
=> https://docs.flatpak.org/en/latest/sandbox-permissions.html
|
||||
|
||||
Якщо описувати влаштування ізоляції програм і їх дозволів Flatpak, то воно має більше спільного з контейнеризацією, хоча автори не задумували проєкт як альтернативу Docker, орієнтуючись саме на користувачів "робочого столу" (Desktop). Чому це так, мені не відомо, адже логіка і принцип роботи Flatpak і Docker - доволі схожі, обидва проєкти мають спільні цілі і у відомих мені випадках можуть бути взаємозамінними.
|
||||
|
||||
Якщо коротко, то ізоляція програми Flatpak для кінцевого користувача зумовлена наступними базовими критеріями.
|
||||
|
||||
### Ідентифікатори програм
|
||||
|
||||
Назви програм, в екосистемі Flatpak, мають стандартизований формат назви, який запобігає конфліктам простору імен (і відповідно - файловими шляхами). Зокрема у випадку, якщо вони мають ідентичну назву, але походять від іншого постачальника або є однойменним форком існуючої програми. Повний перелік вимог до йменування є в документації Application ID:
|
||||
=> https://docs.flathub.org/docs/for-app-authors/requirements#application-id
|
||||
|
||||
Тому при створенні програми і тим більше, якщо ви плануєте її подальшу публікацію на Flathub, важливо дотримуватись специфікації та мати можливість підтвердження володіння простором імен / доменом, в якому оголошено назву.
|
||||
|
||||
### Файлова система
|
||||
|
||||
Файлова система в контексті Flatpak характеризується специфікою її розташування відносно батьківської системи. А саме - в ізольованому просторі імен, що відноситься до умовної "програми" Flatpak. Більше того, щоб зберігати файли у батьківській системі (яка по суті для пісочниці є "зовнішньою") програмі Flatpak потрібно надати відповідний доступ при оголошенні маніфесту.
|
||||
|
||||
Наприклад, якщо програма в Linux стандартно зберігає дані профілю користувача в теці:
|
||||
```
|
||||
~/.app
|
||||
```
|
||||
то в маніфесті Flatpak цей шлях має бути оголошений атрибутом `--persist=.app` і таким чином, реальний шлях до профілю буде:
|
||||
```
|
||||
~/.var/app/org.domain.app-id/.app
|
||||
```
|
||||
Те само стосується й інших каталогів (`share`, `usr` і тд), що планується використовувати із-зовні.
|
||||
|
||||
Також, аргумент `persist` вказує на те, що дані потрібно зберегти після завершення роботи програми Flatpak, оскільки всі дані (окрім виконавчих файлів програми) в процесі роботи зберігаються у тимчасовому сховищі і будуть очищені. По цій причині, ви також не зможете просто дістатись до користувацьких ресурсів пісочниці, оскільки вони зберігатимуться десь у тимчасових файлах з рандомним хешем замість назви файлу, якщо не залінкувати їх на-зовні у маніфесті.
|
||||
|
||||
Окрім згаданого вище `persist`, існують і додаткові дозволи на використання певних каталогів, таких як наприклад ~/Download. Усі ці дозволи в процесі будуть підсвічені на Flathub (чи в центрі застосунків) як необхідні для роботи програми, і надмірне їх використання без зайвої необхідності може відлякувати юзерів, що не хочуть надавати невідомому застосунку забагато прав доступу. Тому варто їх вказувати тільки тоді, коли програма того дійсно потребує.
|
||||
|
||||
### Інтерфейси
|
||||
|
||||
Як і у випадку з файловою системою, потрібно також явно оголошувати які саме інтерфейси та сокети потрібні для роботи вашої програми. У більшості випадків, програма потребуватиме доступу до Інтернет, тому для неї вказується запит на `--share=network` або `--share=ipc`, якщо потрібен доступ до спільної пам'яті. Програми на базі серверу X11, потребуватимуть `--socket=x11` і так далі. Все це є в документації:
|
||||
=> https://docs.flatpak.org/en/latest/sandbox-permissions.html#standard-permissions
|
||||
тому в рамках даного матеріалу розглядати окремо не будемо.
|
||||
|
||||
## Маніфест
|
||||
|
||||
Маніфест в контексті Flatpak - це доволі простий, але й водночас - головний текстовий файл у форматі `.yml` або `.json`, у якому вказані:
|
||||
|
||||
* платформа та її версія
|
||||
* SDK
|
||||
* дозволи програми
|
||||
* параметри зовнішніх інтерфейсів
|
||||
* аргументи запуску
|
||||
* перелік модулів та інструкції для їх послідовної збірки
|
||||
* інструкції очищення після збірки пакунку
|
||||
|
||||
По суті, цього невеличкого файлу достатньо для запуску вашої програми з будь якого пристрою, підключеного до мережі Інтернет, оскільки його зміст вказує тільки на те, звідки завантажити компоненти, яка в них очікувана контрольна сума, та як саме їх зкомпілювати на вказаному у маніфесті середовищі.
|
||||
|
||||
Щоб не писати багато, пропоную приклад двох своїх маніфестів:
|
||||
|
||||
=> https://github.com/twisterarmy/twister/blob/main/io.github.twisterarmy.twister.json twister p2p
|
||||
=> https://github.com/kvazar-network/kevacoin/blob/kvazar/io.github.kvazar_network.kevacoin-qt.json KevaCoin
|
||||
|
||||
Ви можете обрати будь який інший маніфест, що краще відповідає вимогам саме вашої програми - їх там наразі близько чотирьох тисяч:
|
||||
=> https://github.com/orgs/flathub/repositories
|
||||
|
||||
Вважаю, що розглядати опції в рамках одного матеріалу немає сенсу, оскільки все має бути інтуїтивно зрозуміло для тих, хто цікавиться даною темою. Особисто я не користуюсь жодними CLI утилітами і просто створюю цей файл в ручну для проєкту, для якого планую створити збірку Flatpak. Якщо ви проєктуєте нову програму з нуля, а не портуєте спадковий код вже існуючої програми, то рекомендую базовий патерн https://gitlab.gnome.org/World/Rust/gtk-rust-template, за допомогою якого також можете згенерувати новий десктоп проєкт з CLI утилітою на Python, що постачається в репозиторії.
|
||||
|
||||
Для компіляції та встановлення програми з валідного маніфесту, достатньо однієї команди:
|
||||
|
||||
``` bash
|
||||
flatpak-builder --force-clean build\
|
||||
--install-deps-from=flathub\
|
||||
--install\
|
||||
--repo=repo\
|
||||
--user\
|
||||
org.domain.app-id.json
|
||||
```
|
||||
* де `org.domain.app-id.json` - ваш файл маніфесту
|
||||
|
||||
## Збірка пакунку
|
||||
|
||||
Збірка, або бандл (bundle) - це зкомпільований та оптимізований в реліз файл з розширенням `.flatpak`, який по суті є аналогом пакунку встановлення `.exe` у системах Windows. На відміну від "сирого" маніфесту, де вам потрібно для запуску програми завантажувати первинний код та компілювати його на слабкому залізі, ви можете зробити те само на більш потужному пристрої і передати вже готовий файл збірки на флешці.
|
||||
|
||||
Наприклад, щоб зібрати пакунок, з теки, де знаходиться репозиторій маніфесту, виконується команда:
|
||||
|
||||
``` bash
|
||||
flatpak build-bundle repo app-id.flatpak org.domain.app-id.json
|
||||
```
|
||||
* `repo` - тека з локальним репозиторієм Flatpak
|
||||
* `app-id.flatpak` - назва пакунку для генерації
|
||||
* `org.domain.app-id.json` - файл маніфесту
|
||||
|
||||
Цільовий пристрій, на якому запускається файл інсталяції, тільки дозавантажить необхідну платформу, якщо така не була встановлена раніше (при встановленні інших Flatpak застосунків). Для встановлення в користувацький простір (є ще варіант глобального встановлення від `root`)
|
||||
|
||||
``` bash
|
||||
flatpak install --user app-id.flatpak
|
||||
```
|
||||
* де `app-id.flatpak` - назва файлу з попереднього кроку
|
||||
|
||||
Щоб не передавати пакунки `.flatpak` на флешках (і не тільки) й було створено хостинг Flathub, про який декілька слів нижче!
|
||||
|
||||
## Flathub
|
||||
|
||||
Flathub - це безкоштовний хостинг для пакунків Flatpak. Утім, не все з ним так просто як може здаватись, оскільки публікація пакунку на даній платформі потребує певного контролю якості та відповідності програми вимогам сервісу.
|
||||
|
||||
### Публікація
|
||||
|
||||
Суть публікації пакунку на Flathub полягає в створенні форку ініціативного репозиторію (https://github.com/flathub/flathub), в якому створюється окрема гілка для подальшого запиту на додавання (https://github.com/flathub/flathub/pulls).
|
||||
|
||||
До PR, окрім файлу маніфесту, додається ще один, схожий до маніфесту файл metainfo (https://docs.flathub.org/docs/for-app-authors/metainfo-guidelines) у форматі XML. Наприклад для twister p2p - він виглядає так
|
||||
=> https://github.com/twisterarmy/flathub/blob/twister-bundle/io.github.twisterarmy.twister.metainfo.xml
|
||||
* а саме: містить назву, опис проєкту, версію збірки а також скріншоти та деяку іншу інформацію, необхідну для коректного відображення на сайті каталогу.
|
||||
|
||||
Після модерації, ваш проєкт буде (або не буде) розміщено в офіційному списку постачальників (https://github.com/orgs/flathub/repositories) Flathub, а вам (у разі схвалення) - надано статус майнтейнера до відповідного репозиторію для його подальших оновлень.
|
||||
|
||||
Опціонально, постачальники можуть отримати верифікований статус та інші фічі для подальшого просування власного проєкту.
|
||||
|
||||
### Вимоги до публікації
|
||||
|
||||
Основною вимогою до усіх застосунків Flathub є наявність графічного інтерфейсу (GUI). Веб-інтерфейс (як у випадку з twister p2p) і тим паче CLI тут не проходять і модератори вимагатимуть від вас або веб-фрейм або лаунчер, по типу Steam. Веб-фрейми мені не подобаються, оскільки надаю перевагу браузеру. Саме тому, проєкт twister p2p я там досі не опублікував і пішов робити twister-control-center на базі GTK 4:
|
||||
=> https://github.com/twisterarmy/twister-control-center
|
||||
та додаткової ліби rust-twistercore-rpc:
|
||||
=> https://github.com/twisterarmy/rust-twistercore-rpc
|
||||
порт якої навіть не знаю коли завершу і чи завершу взагалі.
|
||||
|
||||
Натомість файл `.flatpak`, який просто запускає демон і відкриває вікно в браузері через `xdg-open`, було розміщено на GitHub, в розділі стабільних релізів:
|
||||
=> https://github.com/twisterarmy/twister/releases/download/0.1.1/twister.flatpak
|
||||
|
||||
По-друге, модератори можуть приколупатись до заміни інструкцій `simple` на `autotools`. Це не зважаючи на те, що майже всі вже додані до їх репозиторію проєкти мають `make` в своїй імплементації. Звісно можна переписати, але я користуюсь офіційними інструкціями для модулів і мені ані цікаво, ані виглядає краще з їх побажанками у маніфесті.
|
||||
|
||||
По-третє, якщо з вимогами GUI чи оптимізацією команд маніфесту, модераторів можна зрозуміти, то таке явище як зміна сортування деяких (не array) елементів в маніфесті - для мене загадка. Наприклад, перенести `finish-args` на початок файлу (коли до цього конструкція була внизу) або побажання доопрацювати інструкції очищення `cleanup` при цьому не надаючи конкретних файлів, які не влаштовують.
|
||||
|
||||
Коротше таке, я спробував, але не в моїх інтересах туди пробиватись, для мене головне, щоб юзер міг скачати. Наразі він може зробити це на GitHub, в розділі релізів. Можливо, повернусь до питань модерації через рік-другий :) З іншого боку, може це й на краще, оскільки проєкт Flathub орієнтований на десктоп користувачів, і це мотивує програмістів створювати більш якісний контент, аніж публікація різноманітного сміття, як це часто відбувається на crates, packagist, npm - де взагалі ручна модерація відсутня.
|
||||
|
||||
## Висновки
|
||||
|
||||
В принципі, мій перший досвід виявився позитивним, після збірки вже другої програми, подумую над іншими проєктами, оскільки перевстановлюю системи часто і кожного разу доводиться звідкись збирати чи то Berkeley DB чи то Boost, або стару версію Qt. Тут же я можу просто зібрати пакунок на робочій станції і потім легко поставити його на будь якому пристрої та операційній системі, наприклад на слабкому ноутбуці не від'їдаючи батарею.
|
||||
|
||||
Сподіваюсь, матеріал буде комусь корисним, можливо щось згадаю то доповню!
|
||||
32
public/uk/freetube-the-private-youtube-client.gmi
Normal file
32
public/uk/freetube-the-private-youtube-client.gmi
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
# FreeTube - приватний перегляд YouTube
|
||||
|
||||
FreeTube - це конфіденційно-орієнтований клієнт з відкритим кодом для перегляду відео на YouTube.
|
||||
|
||||
Написаний на базі Node.js / Electron.
|
||||
|
||||
В стандартних налаштуваннях використовує випадковий проксі-сервер Invidious:
|
||||
|
||||
=> https://invidious.io
|
||||
|
||||
Це запобігає відслудковуванню користувача і формуванню персоналізованих списків.
|
||||
Метод підключення та провайдер може бути вибраний вручну, якщо така потреба є.
|
||||
|
||||
Кожен може стати таким провайдером, якщо сервер відповідає певним умовам:
|
||||
|
||||
=> https://docs.invidious.io/instances/#rules-to-have-your-instance-in-this-list
|
||||
|
||||
Окрім того, що ретрансляція відео FreeTube не містить реклами, клієнт працює у режимі створення локальних підписок, плейлистів, вподобань, які за потреби можна експортувати в JSON чи XML на інший пристрій без участі третіх сторін.
|
||||
Такий підхід дозволяє переглядати виключно той контент, який подобається саме вам, і ніхто не матиме доступу до ваших персональних колекцій.
|
||||
|
||||
Серед функцій - гнучкі налаштування інтерфейсу, зручне завантаження відео, аудіо та субтитрів локально у різній якості, щоправда максимальна якість такого відео обмежена 1080p / 60fps, чого в принципі достатньо для колекції "в дорогу" де немає Інтернет.
|
||||
|
||||
Якщо ж є потреба зберігати оригінальні відео, варто звернути увагу на утиліту yt-dlp:
|
||||
|
||||
=> https://github.com/yt-dlp/yt-dlp
|
||||
|
||||
Клієнт орієнтований в першу чергу на десктоп, може працювати в різних операційних системах та архітектурах.
|
||||
Для встановлення в Linux - доступні готові пакети "deb", "rpm", "appimage", "flatpak" та інші; також є готові збірки останніх версій для Windows і MacOS.
|
||||
|
||||
Завантажити FreeTube можна на офіційному сайті:
|
||||
|
||||
=> https://freetubeapp.io
|
||||
213
public/uk/gemini-protocol-as-http-alternative.gmi
Normal file
213
public/uk/gemini-protocol-as-http-alternative.gmi
Normal file
|
|
@ -0,0 +1,213 @@
|
|||
# Протокол Gemini як альтернатива HTTP
|
||||
|
||||
Gemini - мережний протокол прикладного рівня, в своїй основі є спадкоємцем протоколу Gopher.
|
||||
|
||||
Орієнтований на мінімалізм та конфіденційність, оскільки виключає використання таких веб-технологій як Cookies та JavaScript, а формат даних, що передається - обмежений текстом або бінарними даними без підтримки стиснення та фонового завантаження зі сторонніх ресурсів. Обов'язковим є захист трафіку сертифікатом TLS.
|
||||
|
||||
Не зважаючи на простоту, протокол цілком багатофункціональний і дозволяє працювати з різними типами ресурсів: от як хостинг статичних файлів для персональних сторінок так і системи з авторизацією та обробкою запитів користувача - форуми, пошукові системи, організація радіо та відео стрімів, обмін зображеннями та іншими мультимедійними даними.
|
||||
|
||||
Враховуючи архітектуру, Gemini здебільшого буде цікавий тим, кого не влаштовує "роздутість" сучасного HTTP; стане в нагоді користувачам командного рядка, E-ink планшетів.
|
||||
|
||||
## Термінологія
|
||||
|
||||
Як і в багатьох екосистемах, для Gemini характерна своя термінологія, знання якої допоможе краще розуміти контекст і формувати пошукові запити:
|
||||
|
||||
* Gemini space - екосистема Gemini, подібно терміну "Fediverse" - для федеративної тематики
|
||||
* Capsule - капсула, веб-сайт - назва протоколу походить від тематики космічної програми, тому багато проєктів наслідують концепцію у своїх назвах
|
||||
* Gemlog - блог, персональна сторінка, фід профілю
|
||||
|
||||
## Розмітка
|
||||
|
||||
### Gemtext
|
||||
|
||||
Текстові ресурси gemtext - це звичайний текст (MIME text/gemini), схожий до Markdown, який опціонально містить наступні мета-теги на початку кожного рядка:
|
||||
|
||||
```
|
||||
# h1
|
||||
## h2
|
||||
### h3
|
||||
|
||||
=> gemini://geminiprotocol.net 1965-01-19 Gemini
|
||||
|
||||
> цитата
|
||||
|
||||
* елемент списку 1
|
||||
* елемент списку 2
|
||||
|
||||
` ` ` заголовок, назва файлу або розширення для підсвітки синтаксису (якщо підтримується)
|
||||
код
|
||||
` ` `
|
||||
```
|
||||
|
||||
У розмітці Gemtext не використовуються декоративні технології накшталт CSS, при цьому завдання відображення ресурсу повністю делеговане клієнтові.
|
||||
|
||||
Різні браузери по-різному декорують вміст, деякі додають відступи.
|
||||
Тому головний принцип створення крос-браузерних сторінок простий: розмітка має зручно читатися у вигляді початкового коду.
|
||||
|
||||
### Gemfeed
|
||||
|
||||
Оскільки текстовий регламент протоколу не передбачає використання мета-тегів, такі стандарти сповіщень як Atom та RSS, без зовнішніх засобів інтеграції, в Gemini - не застосовні.
|
||||
|
||||
Незважаючи на це, підписки можливі, зокрема - засобами стандарту Gemfeed для інтерпретації браузером змін документу Gemtext.
|
||||
Наприклад, в браузері Lagrange, відстежувати оновлення сторінки можна за допомогою меню Bookmarks - Subscribe to page… і обрати відповідний сторінці спосіб - підписка при зміні заголовків на сторінці або за зміною дат у посиланнях.
|
||||
|
||||
Відстеження за датою посилань
|
||||
|
||||
У цьому підході здійснюється відстеження за датою, що вказана наступною за посиланням у форматі ISO 8601 (Y-m-d), наприклад:
|
||||
|
||||
```
|
||||
# Заголовок сторінки виконує роль заголовка стрічки
|
||||
|
||||
Вміст параграфа ігнорується у відстеженні
|
||||
|
||||
=> /index.gmi будь-яке посилання, ігнорується
|
||||
|
||||
## Підрозділ сторінки, ігнорується
|
||||
|
||||
Довільний вміст підрозділу, що ігнорується
|
||||
|
||||
## Публікації
|
||||
|
||||
=> /pub1.gmi 2024-01-28 Посилання на першу публікацію - відстежується
|
||||
=> /pub2.gmi 2024-01-29 Посилання на другу публікацію - відстежується
|
||||
=> /pub3.gmi Посилання публікацію - не відстежується (оскільки не містить дати)
|
||||
=> /pub4.gmi Посилання публікацію - не відстежується (оскільки дата є частиною заголовка і розташована зправа) 2024-01-30
|
||||
```
|
||||
|
||||
Таким чином, документ не втрачає зручності для візуального сприйняття людиною і при цьому містить мета-інформацію, зрозумілу для програмного інтерпретатора в браузері, що відслідковує сторінку.
|
||||
|
||||
Єдиний недолік такого підходу полягає в тому, що оновлення не можна отримувати частіше ніж раз на добу. Як заявлено в документації, це пов'язано з часовими зонами.
|
||||
|
||||
Відстеження заголовків
|
||||
|
||||
Альтернативний підхід, який відстежує зміни у заголовках документу:
|
||||
|
||||
```
|
||||
# Мій блог, заголовок стрічки
|
||||
|
||||
Параграф опису
|
||||
|
||||
## Перша публікація - відстежується
|
||||
|
||||
Опис першої публікації
|
||||
|
||||
=> /pub1.gmi Читати
|
||||
|
||||
## Друга публікація - відстежується
|
||||
|
||||
Опис другої публікації
|
||||
|
||||
=> /pub2.gmi Читати
|
||||
|
||||
...
|
||||
```
|
||||
|
||||
## Коди статусів
|
||||
|
||||
Протокол Gemini має власний реєстр кодів заголовків, відмінний від типових для HTTP 200, 301, 404, 500, тощо
|
||||
|
||||
* 10-19 - input expected - очікується введення - використовується для відправлення та отримання даних форм
|
||||
* 20-29 - success - код 20 аналогічний коду 200 в HTTP
|
||||
* 30-39 - redirection - діапазон переадресації, у пакеті, що відправляється, код зазвичай супроводжується мета-посиланням: code + link + \n\r + text
|
||||
* 40-49 - temporary failure
|
||||
* 50-59 - permanent failure
|
||||
* 60-69 - client certificates - у Gemini сертифікати використовуються для ідентифікації та авторизації користувачів
|
||||
|
||||
Клієнт зобов'язаний відхиляти будь-який код менше 10 або більше 69, при цьому повідомити користувача.
|
||||
У невизначених випадках пріоритет буде відданий коду з початковим значенням діапазону, наприклад, 10 для 11 або 20 для 27.
|
||||
|
||||
## Обробка запитів
|
||||
|
||||
Протокол передбачає обмін пакетами із заголовками довжиною максимум 1024 байт. У цю довжину необхідно вмістити мета інформацію про пакет - наприклад рядок URI та/або дані введення користувача.
|
||||
|
||||
Текстові дані мають бути закодовані у стандарт RFC 3986 (відомий такими функціями, як urlencode). Якоюсь мірою це скорочує корисний обсяг заголовка при використанні наприклад кирилиці.
|
||||
|
||||
Тіло пакету складається із "сирих" текстових або бінарних даних без стиснення; сервер закриває з'єднання після надсилання останнього байту.
|
||||
|
||||
За допомогою статусів групи "10", що відправляються клієнту, сервер здатний запитувати введення користувача (замість звичних форм, у браузерах Gemini - це спливаюче текстове вікно)
|
||||
Після отримання та обробки даних, сервер зазвичай повертає статус "20", статус "51" (не знайдено) або переадресацію на цільову сторінку з кодом "30".
|
||||
|
||||
Приклад типового пакету для текстової сторінки "Hello World":
|
||||
|
||||
```
|
||||
20 text/gemini; charset=utf-8; lang=en\r\nHello%20world%21
|
||||
```
|
||||
|
||||
## Клієнт
|
||||
|
||||
Щоб відкрити ресурс з адресою `gemini://` потрібен спеціальний браузер, що стандартно працює з портом `1965`
|
||||
|
||||
Користувачі GUI можуть почати з популярних Lagrange, Eva, Kristall, Castor і т.д.
|
||||
|
||||
Що варто знати:
|
||||
|
||||
* Оскільки більшість клієнтів повертають одно-текстове рядкове поле запиту, додати новий рядок можна комбінацією клавіш Shift+Enter. Розширити спосіб введення можна за допомогою суміжного протоколу Titan, але розляд цього способу вартує окремого матеріалу.
|
||||
* У протоколі Gemini немає webstorage та cookies, тому деякі інтерактивні сайти для функцій авторизації використовують сертифікати, які також можуть використовуватись для швидкої зміни облікового запису в браузері.
|
||||
* Замість фідів RSS є вбудовані в браузер інструменти відстеження контенту (див. Gemfeed)
|
||||
|
||||
## Сервер
|
||||
|
||||
Поняття "сервер" у середовищі Gemini може бути не звичним для користувачів веб, які звикли до поширених веб проксі Nginx або Apache "на всі випадки". Термін часто передбачає повноцінний сервіс для конкретного завдання, що резервує за собою окремий системний хост і порт.
|
||||
|
||||
У каталозі "awesome-gemini" представлено велику кількість таких рішень:
|
||||
|
||||
=> https://github.com/kr1sp1n/awesome-gemini
|
||||
|
||||
Наприклад, для запуску простої статики підійде сервер Agate (Rust). При цьому назва звичного index.html залежатиме від обраного рішення, для Agate - це index.gmi але для іншого серверу постфікс може відрізнятись.
|
||||
|
||||
Запуск динамічних ресурсів часто передбачає розробку власного сокет-серверу для реалізації специфіки окремо взятої програми.
|
||||
|
||||
Веб-розробникам простіше зрозуміти принцип роботи "server-side" на прикладі декількох файлів gemini-php:
|
||||
|
||||
=> https://github.com/eapl-gemugami/gemini-php
|
||||
|
||||
Утім, в нових проєктах краще використовувати більш актуальні рішення, наприклад, з простих - форк бібліотеки Titan-II:
|
||||
|
||||
=> https://github.com/YGGverse/titan-II
|
||||
|
||||
Приклади реалізації можна подивитись у коді β-Doku - Gemini-проксі для DokuWiki:
|
||||
|
||||
=> https://github.com/YGGverse/bdoku
|
||||
|
||||
Щоб запускати різні сервіси на одному IP (не змінюючи стандартний порт), зручно встановити загальний проксі-сервер, який здійснюватиме маршрутизацію запитів на відповідну адресу/інтерфейс або на зовнішній сервер.
|
||||
|
||||
Якщо в HTTP - це Apache / Nginx, то для протоколу Gemini підійдуть Gmid (C):
|
||||
|
||||
=> https://gmid.omarpolo.com/
|
||||
|
||||
або Twins (Go):
|
||||
|
||||
=> https://code.rocket9labs.com/tslocum/twins
|
||||
|
||||
З другим помічені деякі проблеми з передачею довгих текстів, тому для початківців, бажано розпочати роботу з Gmid, який наразі активно розвивається та має дружній фідбек від розробника.
|
||||
|
||||
## З чого почати
|
||||
|
||||
=> gemini://geminiprotocol.net Домашня сторінка проєкту
|
||||
=> gemini://geminispace.info Одна з пошукових систем
|
||||
=> gemini://tlgs.one Ще одна пошукова система
|
||||
=> gemini://chat.mozz.us Чат в режимі онлайн стріму (хороший тест для вашого клієнта)
|
||||
=> gemini://bbs.geminispace.org Дошка оголошень і тематичні форуми
|
||||
=> gemini://station.martinrue.com Соціальна мережа за типом twitter
|
||||
=> gemini://hd.206267.xyz Офіційний Fediverse інстанс від розробників Tootik
|
||||
=> gemini://meadow.hmmm.zt.ua Україномовний інстанс Tootik
|
||||
=> gemini://gemlog.blue Найпростіший спосіб опублікувати свої сторінки в мережі Gemini
|
||||
=> gemini://cities.yesterweb.org Хостинг з піддоменом, підтримкою Titan і WebDAV
|
||||
=> gemini://flounder.online Хостинг з агрегатором останніх записів, є SFTP
|
||||
=> gemini://astrobotany.mozz.us ASCII гра з догляду за рослинами, що затягує :)
|
||||
|
||||
## Схожі протоколи
|
||||
|
||||
* Gopher
|
||||
* Guppy
|
||||
* Nex
|
||||
* Scorpion
|
||||
* Scroll
|
||||
* Spartan
|
||||
* Text
|
||||
|
||||
## Дивіться також
|
||||
|
||||
=> gmid-server-for-gemini-protocol.gmi Gmid - багатофункціональний сервер для Gemini
|
||||
=> nex-lightweight-gemini-alternative.gmi Протокол NEX - легка альтернатива Gemini
|
||||
=> ukrainian-geminispace.gmi Український Geminispace
|
||||
122
public/uk/gmid-server-for-gemini-protocol.gmi
Normal file
122
public/uk/gmid-server-for-gemini-protocol.gmi
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
# Gmid - багатофункціональний сервер для Gemini
|
||||
|
||||
Gmid - багатофункціональний сервер з відкритим кодом для протоколу Gemini.
|
||||
|
||||
Зокрема, його зручно використовувати у якості проксі серверу для віртуальних хостів, аналогічно тому як цю функцію виконує Nginx для HTTP.
|
||||
|
||||
Це може бути зручно, коли немає змоги піднімати для кожного серверу маску підмережі, або коли сайт працює на VPS з одним виділеним IP.
|
||||
|
||||
## Встановлення
|
||||
|
||||
Написаний Gmid на "C", перед його збіркою потрібно додати наступні бібліотеки:
|
||||
|
||||
```
|
||||
apt install bison byacc
|
||||
```
|
||||
|
||||
Буде правильним запускати і відповідно виконувати процес Gmid від окремого користувача, якого спочатку створимо та виконаємо вхід:
|
||||
|
||||
```
|
||||
useradd -m gmid
|
||||
su gmid
|
||||
```
|
||||
|
||||
Клонуємо останню версію з офіційного дзеркала на GitHub і виконуємо компіляцію:
|
||||
|
||||
```
|
||||
git clone https://github.com/omar-polo/gmid.git
|
||||
cd gmid
|
||||
./configure
|
||||
make
|
||||
```
|
||||
|
||||
## Налаштування reverse-proxy
|
||||
|
||||
Нижче описаний приклад створення двох віртуальних хостів "host1.com" та "host2.com", які працюють на умовних адресах "1.2.3.4:1965" та "4.3.2.1:1965" відповідно.
|
||||
|
||||
Таким чином, файл конфігурації виглядатиме так:
|
||||
|
||||
``` /home/gmid/gmid.conf
|
||||
server "host1.com" {
|
||||
|
||||
listen on 0.0.0.0 port 1965
|
||||
|
||||
cert "/home/gmid/host/host1.com/cert.pem"
|
||||
key "/home/gmid/host/host1.com/key.rsa"
|
||||
|
||||
proxy {
|
||||
sni "host1.com"
|
||||
relay-to 1.2.3.4 port 1965
|
||||
verifyname off
|
||||
}
|
||||
}
|
||||
|
||||
server "host2.com" {
|
||||
|
||||
listen on 0.0.0.0 port 1965
|
||||
|
||||
cert "/home/gmid/host/host2.com/cert.pem"
|
||||
key "/home/gmid/host/host2.com/key.rsa"
|
||||
|
||||
proxy {
|
||||
sni "host2.com"
|
||||
relay-to 4.3.2.1 port 1965
|
||||
verifyname off
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Створення сертифікатів
|
||||
|
||||
На прикладі конфігурації вище, додамо само-підписаний сертифікат на прикладі "host1.com", необхідний для роботи протоколу Gemini.
|
||||
|
||||
Аналогічним способом створюється й сертифікат для "host2.com", замінивши значення атрибуту "CN":
|
||||
|
||||
```
|
||||
mkdir /home/gmid/host/host1.com
|
||||
cd /home/gmid/host/host1.com
|
||||
openssl req -x509 -newkey rsa:4096 -keyout key.rsa -out cert.pem -days 3650 -nodes -subj "/CN=host1.com"
|
||||
```
|
||||
|
||||
## Автозапуск
|
||||
|
||||
Щоб наш проксі-сервер стартував разом з системою і працював як процес "systemd", додамо для Gmid юніт:
|
||||
|
||||
``` /etc/systemd/system/gmid.service
|
||||
[Unit]
|
||||
Description=gmid
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=gmid
|
||||
Group=gmid
|
||||
WorkingDirectory=/home/gmid/
|
||||
ExecStart=/home/gmid/gmid/gmid -c /home/gmid/gmid.conf -f -v
|
||||
StandardOutput=file:/home/gmid/output.log
|
||||
StandardError=file:/home/gmid/debug.log
|
||||
Restart=on-failure
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
* "-f" - запуск в режимі "foreground", інакше процес стартуватиме у фоновому режимі без журналювання
|
||||
* "-v" - або "verbose" для звітів відлагодження
|
||||
|
||||
Оновлюємо конфігурацію та запускаємо сервер:
|
||||
|
||||
```
|
||||
systemctl daemon-reload
|
||||
systemctl enable gmid
|
||||
systemctl start gmid
|
||||
```
|
||||
|
||||
## Посилання
|
||||
|
||||
=> gemini://gmid.omarpolo.com Офіційна сторінка проєкту
|
||||
=> https://github.com/omar-polo/gmid Дзеркало на GitHub
|
||||
|
||||
## Дивіться також
|
||||
|
||||
=> gemini-protocol-as-http-alternative.gmi Протокол Gemini як альтернатива HTTP
|
||||
56
public/uk/grab-video-from-rezka-hd-mirror-with-yt-dlp.gmi
Normal file
56
public/uk/grab-video-from-rezka-hd-mirror-with-yt-dlp.gmi
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
# Завантаження відео з сайтів Rezka HD через плагін yt-dlp
|
||||
|
||||
Інструкція зі встановлення rezka_yt_dlp_plugin в Linux, для завантаження останніх релізів озвучки з дзеркал Rezka. Може бути корисною для створення роздач BitTorrent, або для локального перегляду відео.
|
||||
|
||||
Спочатку потрібно встановити утиліту yt-dlp зручним способом. Якщо у вас вже розгорнуто інфраструктуру Python, найпростіше це зробити з pip:
|
||||
|
||||
``` bash
|
||||
pip install yt-dlp
|
||||
```
|
||||
|
||||
Наступним кроком, встановлюємо сам плагін. Є різні способи, але я робив так:
|
||||
|
||||
``` bash
|
||||
mkdir -p ~/.config/yt-dlp/plugins
|
||||
cd ~/.config/yt-dlp/plugins
|
||||
git clone https://github.com/gnfalex/rezka_yt_dlp_plugin.git
|
||||
yt-dlp --verbose
|
||||
5. `nano ~/.config/yt-dlp/plugins/rezka_yt_dlp_plugin/yt-dlp.conf
|
||||
```
|
||||
|
||||
Перевірити успішність встановлення плагіну можна так:
|
||||
|
||||
``` bash
|
||||
yt-dlp --verbose
|
||||
```
|
||||
|
||||
Змінити стандартну конфігурацію (зокрема вказати звукову доріжку та URL) можна у файлі:
|
||||
|
||||
```
|
||||
~/.config/yt-dlp/plugins/rezka_yt_dlp_plugin/yt-dlp.conf
|
||||
```
|
||||
* або пропустити, використовуючи у такому випадку аргументи CLI
|
||||
|
||||
Відео завантажується наступним чином:
|
||||
|
||||
``` bash
|
||||
cd ~/Downloads
|
||||
yt-dlp --config-location ~/.config/yt-dlp/plugins/rezka_yt_dlp_plugin/yt-dlp.conf URL
|
||||
```
|
||||
|
||||
або ж просто наступною командою, обравши звукову доріжку вручну
|
||||
|
||||
``` bash
|
||||
yt-dlp URL
|
||||
```
|
||||
|
||||
для вибору сезону та епізоду:
|
||||
|
||||
``` bash
|
||||
--match-filter "season=1&episode=2"
|
||||
```
|
||||
|
||||
## Посилання
|
||||
|
||||
=> https://github.com/gnfalex/rezka_yt_dlp_plugin
|
||||
=> https://github.com/yt-dlp/yt-dlp#installing-plugins
|
||||
239
public/uk/half-life-on-linux-using-xash3d-fwgs-engine.gmi
Normal file
239
public/uk/half-life-on-linux-using-xash3d-fwgs-engine.gmi
Normal file
|
|
@ -0,0 +1,239 @@
|
|||
# Half-Life в Linux на базі рушія Xash3D / FWGS
|
||||
|
||||
Half-Life - чудова гра свого часу, яка досі має чимало шанувальників та високий онлайн.
|
||||
|
||||
Вона стандартно працює в Linux через Steam, утім варто знати й про таку альтернативу рушія з відкритим кодом, як Xash3D/FWGS:
|
||||
|
||||
=> https://github.com/FWGS/xash3d-fwgs
|
||||
|
||||
## Встановлення
|
||||
|
||||
Для встановлення, знадобиться підтримка архітектури i386:
|
||||
|
||||
```
|
||||
dpkg --add-architecture i386
|
||||
apt update
|
||||
apt install build-essential gcc-multilib g++-multilib python3 libsdl2-dev:i386 libfontconfig-dev:i386 libfreetype6-dev:i386
|
||||
export PKG_CONFIG_PATH=/usr/lib/i386-linux-gnu/pkgconfig
|
||||
```
|
||||
|
||||
Після цього клонуємо репозиторій та збираємо бінарний пакет:
|
||||
|
||||
```
|
||||
git clone https://github.com/FWGS/xash3d-fwgs.git
|
||||
cd xash3d-fwgs
|
||||
./waf configure -T release
|
||||
./waf build
|
||||
```
|
||||
|
||||
Коли рушій буде скомпільовано, його можна перенести у потрібну теку, де звичайно зберігаються ігри:
|
||||
|
||||
```
|
||||
./waf install --destdir=/path/to/any/output/directory
|
||||
```
|
||||
|
||||
Наступним кроком, потрібно придбати саму гру (до якої і досі виходять оновлення).
|
||||
|
||||
Купити гру можна безпосередньо у Steam за посиланням:
|
||||
|
||||
=> https://store.steampowered.com/app/70/HalfLife
|
||||
|
||||
Зробити це найкраще у свята, коли бувають розпродажі, знижки іноді сягають 90% вартості, тому можна купити повний набір Half-Life, включно з другою версією (про запуск якої в Linux поговоримо окремо).
|
||||
|
||||
Не зважаючи на те, що в офіційній інструкції вказано просто скопіювати файли гри в директорію "valve", насправді при запуску ймовірно буде помилка:
|
||||
|
||||
```
|
||||
Host_InitError: Can't initialize cl_dlls/client.so: vgui.so: cannot open shared object file: No such file or directory
|
||||
```
|
||||
|
||||
Вирішується вона копіюванням файлу "vgui.so" безпосередньо у кореневу теку, де встановлено Xash3D (тобто рівнем вище "valve")
|
||||
|
||||
## Запуск гри
|
||||
|
||||
Запускається гра виконанням бінарного файлу Xash3D. Для цього можливо треба дати відповідні права:
|
||||
|
||||
```
|
||||
chmod +x xash3d
|
||||
xash3d -dev
|
||||
```
|
||||
|
||||
Якщо все зроблено правильно, з'явиться лаунчер рушія з відповідним меню, де можна грати в одиночну гру або в мережі з друзями.
|
||||
|
||||
Щоб відображати консоль в лаунчері, Xash3D запускається з атрибутом "-dev" або "~" під час гри.
|
||||
|
||||
## Майстер сервер
|
||||
|
||||
Майстер сервер використовується для пошуку ігрових серверів, відповідно усі сервери, що ви бачитимете в мультиплеєрі, відправляють свій статус майстер серверу, а той - клієнтові при виборі підключень.
|
||||
|
||||
За замовченням, рушій викуристовує власний майстер mentality.rip:27010
|
||||
|
||||
Змінити його можна в терміналі командами:
|
||||
|
||||
* clearmasters
|
||||
* addmaster IP:port
|
||||
* listmasters
|
||||
|
||||
Також на етапі збірки, змінити можна у вихідному коді, наприклад:
|
||||
|
||||
=> https://github.com/FWGS/xash3d-fwgs/commit/05d9cf895e180f25e6e0cbe33e3f02cd222de3b0
|
||||
|
||||
Якщо планується запуск власного майстера, наразі існує два відкритих рішення:
|
||||
|
||||
### pymaster
|
||||
|
||||
Неофіційна редакція закинутого майстер сервера на Python:
|
||||
|
||||
=> https://github.com/YGGverse/pymaster/tree/v2
|
||||
|
||||
### xash3d-master
|
||||
|
||||
Після релізу редакції pymaster, розробник опублікував офіційну версію на мові Rust:
|
||||
|
||||
=> https://git.mentality.rip/numas13/xash3d-master
|
||||
|
||||
## Ігровий сервер
|
||||
|
||||
Для запуску ігрового серверу, використовується аналогічна збірка Xash3D та файлами з грою, запуск відбувається приблизно так:
|
||||
|
||||
```
|
||||
xash3d -dedicated -port 27015 -ip xx:xx:xx:xx +maxplayers 8 +map crossfire
|
||||
```
|
||||
|
||||
При цьому звісно, не забуваємо відкрити порт:
|
||||
|
||||
```
|
||||
ufw allow 27015
|
||||
```
|
||||
|
||||
Налаштування серверу зберігаються у наступних файлах, по яким треба пройтись окремо
|
||||
|
||||
* valve/server.cfg
|
||||
* valve/skill.cfg
|
||||
* valve/listip.cfg
|
||||
* valve/banned.cfg
|
||||
|
||||
Щоб сервер став доступним у спискі обраного майстра, потрібно також вказати:
|
||||
|
||||
```
|
||||
sv_lan 0
|
||||
public 1
|
||||
```
|
||||
|
||||
### FastDL
|
||||
|
||||
FastDL - це спосіб швидкої передачі ігрових файлів клієнтові. Звичайно організується на базі веб каталогу за допомогою Nginx.
|
||||
|
||||
Структура файлів, що передається, має відповідати стандартному їх розташуванню у "valve", наприклад:
|
||||
|
||||
* /maps
|
||||
* /models
|
||||
* /sound
|
||||
* /materials
|
||||
|
||||
після чого, у файлі "server.cfg" вказується шлях до цільових файлів (де "/fastdl/half-life/" - довільний шлях, якщо корінь зайнятий):
|
||||
|
||||
```
|
||||
sv_downloadurl "http://xx.xx.xx.xx/fastdl/half-life/"
|
||||
sv_allowdownload 1
|
||||
```
|
||||
|
||||
### RESGen
|
||||
|
||||
RESGen - найпростіший спосіб згенерувати файли залежностей для ігрової мапи.
|
||||
|
||||
Наприклад, особливі моделі гравців, для подальшої передачі їх через FastDL.
|
||||
|
||||
Репозиторій проєкту доступний на GitHub:
|
||||
|
||||
=> https://github.com/kriswema/resgen
|
||||
|
||||
Для генерації текстового файлу необхідно вказати цільову мапу на сервері:
|
||||
|
||||
```
|
||||
Linux.64-bit /valve/maps/crossfire.bsp
|
||||
```
|
||||
|
||||
Після чого буде згенеровано приблизно такий файл:
|
||||
|
||||
```
|
||||
// crossfire.res - created with RESGen v2.0.3.
|
||||
// RESGen is made by Jeroen "ShadowLord" Bogers,
|
||||
// with serveral improvements and additions by Zero3Cool.
|
||||
// For more info go to http://resgen.hltools.com
|
||||
|
||||
// .res entries (9):
|
||||
halflife.wad
|
||||
sound/ambience/jetflyby1.wav
|
||||
sound/ambience/siren.wav
|
||||
sound/debris/beamstart11.wav
|
||||
sound/weapons/electro5.wav
|
||||
sound/weapons/mortarhit.wav
|
||||
sound/weapons/sbarrel1.wav
|
||||
sprites/muzzleflash1.spr
|
||||
sprites/steam1.spr
|
||||
models/player/... // тут додаємо нашу кастомну модель гравця
|
||||
```
|
||||
|
||||
Отриманий файл розміщуємо у теці "/valve/maps" поряд з однойменною мапою.
|
||||
|
||||
Таким чином (після перезапуску серверу), нові гравці, що підключились, зможуть бачити відповідні моделі замість стандартних.
|
||||
Моделі будуть завантажуватись усім учасникам гри до локальної теки "/valve/downloaded/models/player/"
|
||||
|
||||
### Боти
|
||||
|
||||
Щоб гравцям не було самотньо в очікуванні, можна додати ботів, які наприклад будуть зникати із появою онлайну.
|
||||
|
||||
Рішень насправді існує багато, але найбільш простий спосіб - це "Bot Number 10":
|
||||
|
||||
=> http://hpb-bot.bots-united.com/downloads.html
|
||||
|
||||
Є офіційна бінарна збірка для Linux:
|
||||
|
||||
=> http://hpb-bot.bots-united.com/releases/bot10_linux.tgz
|
||||
|
||||
Утім, якщо потрібно модифікувати бота, можна зібрати власну версію з початкового коду, яка є частиною "Portable Half-Life SDK":
|
||||
|
||||
=> https://github.com/FWGS/hlsdk-portable/tree/bot10
|
||||
|
||||
```
|
||||
git clone --recursive https://github.com/FWGS/hlsdk-portable.git
|
||||
git checkout bot10
|
||||
cmake -B build -S .
|
||||
cmake --build build
|
||||
```
|
||||
|
||||
Існує також альтернативна збірка "YGGverse":
|
||||
|
||||
=> https://github.com/YGGverse/hlsdk-portable/tree/bot10-yggverse
|
||||
|
||||
Вона дозволяє запускати зконфігурованих ботів а не просто рандомних, як це зроблено в оригіналі.
|
||||
Наприклад, на цьому сервері у якості мішені використовується путін:
|
||||
|
||||
```
|
||||
connect 94.140.114.89:27015
|
||||
```
|
||||
|
||||
## Висновки
|
||||
|
||||
В цілому, хоч в Steam більший онлайн, Xash3D має свою спільноту і можливості для розробки.
|
||||
|
||||
Гра стабільно працює на стареньких PC, а для запуску власного серверу, згодиться мінімальний тариф VPS (в середньому завантаженість CPU складає 15%).
|
||||
|
||||
Якщо тема є цікавою, можливо окремо буде описано спосіб запуску Half-Life 2 на базі рушія Source, наприклад однієї з його версій у відкритому доступі:
|
||||
|
||||
=> https://github.com/nillerusr/source-engine
|
||||
|
||||
## Посилання
|
||||
|
||||
=> https://store.steampowered.com/app/70/HalfLife Придбати файли гри Half-Life в Steam
|
||||
=> https://github.com/FWGS/xash3d-fwgs Офіційна сторінка рушія Xash3D / FWGS
|
||||
=> https://www.svencoop.com/manual/server-config.html Опис параметрів конфігурації сервера
|
||||
=> https://developer.valvesoftware.com/wiki/Server_queries Серверні запити
|
||||
=> https://developer.valvesoftware.com/wiki/Master_Server_Query_Protocol Команди майстер сервера
|
||||
=> https://gamebanana.com/mods/cats/7734 Каталог скінів
|
||||
=> https://github.com/YGGverse/hl-php PHP 8 / Composer бібліотека для веб-розробників
|
||||
=> https://github.com/YGGverse/hlstate Веб рушій на Symfony для організації серверу аналітики
|
||||
|
||||
## Дивіться також
|
||||
|
||||
=> create-half-life-graffiti-logo-in-gimp.gmi Створення графіті Half-Life в GIMP
|
||||
56
public/uk/htcount-visitors-counter-for-access-log.gmi
Normal file
56
public/uk/htcount-visitors-counter-for-access-log.gmi
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
# htcount: лічильник відвідувань сайту на базі access.log
|
||||
|
||||
htcount - системна утиліта, написана мовою Rust, що рахує кількість хостів / хітів на основі даних локального журналу access.log (CLF) і виводить результати у вигляді дампу JSON/API або у форматі кнопки SVG для вставки на сайт.
|
||||
|
||||
По суті, вона влаштована так само, як відомий goaccess - інструмент CLI, який дозволяє аналізувати Веб-трафік без підключення сторонніх сервісів типу Google Analytics.
|
||||
|
||||
## Встановлення
|
||||
|
||||
htcount написано мовою Rust, можливо, вам знадобиться спочатку розгорнути відповідну інфраструктуру для її збірки з початкового коду:
|
||||
=> install-latest-rust-version-on-linux.gmi Встановлення останньої версії Rust в Linux
|
||||
|
||||
``` bash
|
||||
git clone https://github.com/YGGverse/htcount.git && cd htcount
|
||||
cargo build --release
|
||||
sudo install target/release/htcount /usr/local/bin/htcount
|
||||
```
|
||||
* встановлення до `/usr/local/bin/htcount` потрібне в контексті системних дозволів systemd
|
||||
|
||||
### systemd
|
||||
|
||||
``` /etc/systemd/system/htcount.service
|
||||
[Unit]
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStart=/usr/local/bin/htcount\
|
||||
# вкажіть актуальний шлях цільового журналу (див. також --ignore-host)
|
||||
--source /var/log/nginx/access.log\
|
||||
# вкажіть актуальний шлях для розміщення кнопки
|
||||
--export-svg /var/www/path/to/public/counter.svg\
|
||||
# я збирав пакунок від root, де в мене лежать оригінали у якості шаблону
|
||||
--template-svg /root/htcount/default/counter.svg\
|
||||
# оновлення кнопки раз на годину (3600 секунд)
|
||||
--update 3600\
|
||||
# оновлення відвідувачів раз на добу
|
||||
--match-time %%d/%%b/%%Y\
|
||||
# дебаг у файл вимкнено для заощадження терміну служби SSD
|
||||
--debug n
|
||||
# дебаг вимкнено опцією --debug n, можна вказати шлях або драйвер
|
||||
StandardOutput=null
|
||||
# збираємо усі помилки до стандартного розташування системних журналів
|
||||
StandardError=file:///var/log/htcount-error.log
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
* перелік доступних опцій залежить від актуальної версії: `htcount --help`
|
||||
* для інтеграції кнопки на сайт, додайте відповідний код: `<img src="/counter.svg"/>`
|
||||
|
||||
## Посилання
|
||||
|
||||
=> https://crates.io/crates/htcount
|
||||
=> https://en.wikipedia.org/wiki/Common_Log_Format
|
||||
=> https://goaccess.io
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
# Регулювання яскравості монітору iMac в Linux
|
||||
|
||||
Маю відносно старенький девайс iMac 2011 року і довий час користувався ручним регулюванням яскравості монітору командою "xrandr".
|
||||
|
||||
Наприклад, щоб зменишити яскравість до 80%:
|
||||
|
||||
```
|
||||
xrandr --output eDP --brightness 0.8
|
||||
```
|
||||
|
||||
Якось випадково мені довелось залізти в драйвер підсвітки "/sys/class/backlight/radeon"
|
||||
|
||||
Змінивши стандартне значення з "255" до комфортних "50" я був здивований наскільки контрастне відображення вдалось отримати!
|
||||
Вражає, скільки часу провів на пересвіченому моніторі!
|
||||
|
||||
Як виявилось, існує два фактори: живлення на катоди RGB та власне самої підсвітки.
|
||||
|
||||
В залежності від відеокарти, ймовірно, для інших користувачів iMac цього року випуску, команда виглядатиме так (і виконується від "root"):
|
||||
|
||||
```
|
||||
echo 50 > /sys/class/backlight/radeon_bl0/brightness
|
||||
```
|
||||
|
||||
або ж подивіться що у вас в теці (і підставте в команду вище вашу карту):
|
||||
|
||||
```
|
||||
ls /sys/class/backlight
|
||||
```
|
||||
|
||||
Зауважу, що наведена вище інструкція, у моєму випадку, вимагає зміни "acpi_backlight" в значення "native"
|
||||
|
||||
``` /etc/default/grub
|
||||
GRUB_CMDLINE_LINUX_DEFAULT="quiet acpi_backlight=native"
|
||||
```
|
||||
|
||||
Після чого потрібно оновити конфігурацію командою "update-grub" і перезавантажити систему.
|
||||
Остання дія також додасть підтримку сенсору автоматичної яскравості, зокрема в Ubuntu.
|
||||
|
||||
Сподіваюсь, дана замітка стане в нагоді!
|
||||
55
public/uk/index.gmi
Normal file
55
public/uk/index.gmi
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
> ...якщо цьому є творець, то він - революціонер,
|
||||
> експериментатор або вигнанець системи
|
||||
> споконвічного спокою.
|
||||
|
||||
### Ласкаво просимо
|
||||
|
||||
=> traditional-craft-masters-of-ukraine.gmi 2024-06-16 Майстри традиційних ремесел України
|
||||
=> ukrainian-geminispace.gmi 2024-06-16 Український Geminispace
|
||||
|
||||
### Статті
|
||||
|
||||
=> rssto-convert-rss-feeds-into-multiple-formats.gmi 2025-09-03 rssto: конвертація фідів у різні формати
|
||||
=> misfin-postal-satellite-of-geminispace.gmi 2025-09-02 Misfin - поштовий сателіт Geminispace
|
||||
=> htcount-visitors-counter-for-access-log.gmi 2025-08-30 htcount: лічильник відвідувань сайту на базі access.log
|
||||
=> about-fediverse-server-in-the-alternative-networks.gmi 2025-08-30 Про сервер Fediverse в альтернативних мережах
|
||||
=> thoughts-on-tls-on-yggdrasil-and-mycelium-networks.gmi 2025-08-28 Думки стосовно TLS в мережах Yggdrasil та Mycelium
|
||||
=> grab-video-from-rezka-hd-mirror-with-yt-dlp.gmi 2025-08-28 Завантаження відео з сайтів Rezka HD через плагін yt-dlp
|
||||
=> btracker-bittorrent-tracker-in-rust.gmi 2025-08-27 βtracker - BitTorrent агрегатор на базі Rust
|
||||
=> dns-less-email-server-for-the-local-networks.gmi 2025-08-26 Організація поштової скриньки для локальних мереж без DNS
|
||||
=> install-flarum-v2-on-linux.gmi 2025-08-24 Встановлення Flarum v2 в Linux
|
||||
=> prepare-steam-half-life-game-asset-for-the-bittorrent-release.gmi 2025-08-13 Підготовка ігрових файлів Half-Life (Steam) для релізу BitTorrent
|
||||
=> install-aquatic-open-tracker-on-linux.gmi 2025-06-02 Встановлення BitTorrent трекера Aquatic в Linux
|
||||
=> safe-yggdrasil-websites-browsing-with-yggstack.gmi 2025-05-23 Безпечний перегляд сайтів Yggdrasil з Yggstack
|
||||
=> my-thoughts-on-the-modern-uanet-it-segment.gmi 2025-05-17 Мої думки про сучасний ІТ сегмент UANET
|
||||
=> personal-snac-instance-for-yggdrasil-network.gmi 2025-05-11 Налаштування Fedi-сервера Snac для мережі Yggdrasil
|
||||
=> asocial-p2p.gmi 2025-05-09 Граблі соціального P2P
|
||||
=> flatpak-bundle-build.gmi 2025-04-20 Створення пакунку Flatpak
|
||||
=> twister-p2p-decentralized-microblogging-platform.gmi 2025-04-13 twister - децентралізована платформа мікроблогів
|
||||
=> my-first-impressions-of-rust.gmi 2024-10-26 Мої перші враження від Rust
|
||||
=> libhandy-tab-as-gtk-notebook-widget-alternative.gmi 2024-09-07 HdyTab як альтернатива віджету вкладок GtkNotebook
|
||||
=> inefficient-internet-privacy.gmi 2024-09-07 Про конфіденційність в мережі Інтернет
|
||||
=> first-impressions-of-cpp.gmi 2024-09-03 Мої перші враження від C++
|
||||
=> memory-management-in-gtkmm-4.0.gmi 2024-09-02 Керування пам'яттю в gtkmm-4.0
|
||||
=> memory-management-in-gtk-applications.gmi 2024-09-01 Керування пам'яттю в програмах GTK
|
||||
=> first-steps-in-gtk.gmi 2024-08-31 Мої перші кроки в GTK
|
||||
=> nex-lightweight-gemini-alternative.gmi 2024-06-20 Протокол NEX - легка альтернатива Gemini
|
||||
=> mushroom-ink-for-calligraphy.gmi 2024-06-16 Грибні чорнила для каліграфії
|
||||
=> manticore-as-primary-database-usage-issues.gmi 2024-03-25 Незручні моменти в роботі Manticore як основної БД
|
||||
=> chesslablab-open-source-chess-in-php.gmi 2024-03-25 ChesslaBlab - шахи онлайн з відкритим кодом на PHP
|
||||
=> openlegends-tes-legends-card-game-open-source-alternative.gmi 2024-03-20 Розробка карткової гри з відкритим кодом OpenLegends
|
||||
=> fail2ban-startup-failure-fix-on-debian-12.gmi 2024-03-09 Виправлення помилки запуску fail2ban в Debian 12
|
||||
=> gmid-server-for-gemini-protocol.gmi 2024-03-09 Gmid - багатофункціональний сервер для Gemini
|
||||
=> install-latest-rust-version-on-linux.gmi 2024-03-09 Встановлення останньої версії Rust в Linux
|
||||
=> install-latest-golang-version-on-debian-linux.gmi 2024-03-09 Встановлення останньої версії Go в Debian
|
||||
=> yggmail-messenger-with-email-protocol.gmi 2024-03-09 Yggmail - месенджер з поштовим інтерфейсом
|
||||
=> freetube-the-private-youtube-client.gmi 2024-03-08 FreeTube - приватний перегляд YouTube
|
||||
=> imac-monitor-backlight-brightness-setup-in-linux.gmi 2024-03-08 Регулювання яскравості монітору iMac в Linux
|
||||
=> ukrainian-latin-keyboard-layout-on-linux.gmi 2024-03-08 Розкладка української латинки в Linux
|
||||
=> kevacoin-decentralized-database-in-blockchain.gmi 2024-03-08 KevaCoin - децентралізована база даних в блокчейн
|
||||
=> manticore-as-modern-alternative-to-sphinx-search.gmi 2024-03-07 Manticore як сучасна альтернатива Sphinx
|
||||
=> create-half-life-graffiti-logo-in-gimp.gmi 2024-03-07 Створення графіті Half-Life в GIMP
|
||||
=> half-life-on-linux-using-xash3d-fwgs-engine.gmi 2024-03-07 Half-Life в Linux на базі рушія Xash3D / FWGS
|
||||
=> alfis-dns-domain-registration-in-blockchain.gmi 2024-03-06 Alfis DNS - реєстрація домену в блокчейн
|
||||
=> yggdrasil-is-network-with-distributed-routing.gmi 2024-03-06 Yggdrasil - мережа з децентралізованою маршрутизацією
|
||||
=> gemini-protocol-as-http-alternative.gmi 2024-03-06 Протокол Gemini як альтернатива HTTP
|
||||
81
public/uk/inefficient-internet-privacy.gmi
Normal file
81
public/uk/inefficient-internet-privacy.gmi
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
# Про конфіденційність в мережі Інтернет
|
||||
|
||||
У кожного своє розуміння конфіденційності та інформаційної безпеки у рамках різних контекстів. Дехто не переймається темою взагалі, нехтуючи поширенням своїх персональних даних, аргументуючи це їх повною "непотрібністю". Наочним історичним прикладом колись "нікому непотрібної" інформації, був виток облікових даних єврейських громад у фашистській Германії - коли водномить, здавалось би побутові дані стали питанням виживання мільйонів людей. З іншого боку, такі сфери, як об'єктивна журналістика та альтернативні технології зазнають тиску, і сусідня диктатура - тому наглядний приклад, де недавно бравий анон сьогодні боїться писнути "проти" в глибинах своїх мешів.
|
||||
|
||||
Цей матеріал не має на меті когось навчати, переконувати чи нав'язувати паранойю. Тут немає практичних рекомендацій для жодного з тлумачень приватної інформації. Це виключно моя суб'єктивна фіналізація отриманого досвіду по темі інформаційної гігієни, з точки зору користувача, а не спеціаліста сфери безпеки: зокрема, до вивчення того, як працюють мережеві технології та після.
|
||||
|
||||
## Передісторія
|
||||
|
||||
Мій шлях в мережі Інтернет почався незадовго до популяризації його в Україні. Не зважаючи на той факт, що технологія вже давно була поширена на заході, в Україні, мережа все ще сприймалась не серйозно і через тодішню швидкість, слугувала більше для пошуку друкованої інформації (смішно задувати, але вже тоді Інтернет був джерелом прибутку для піратського передруку брошур на ринку "Караваєві Дачі") тоді ніхто не міг подумати, що Інтернет стане основою сучасної торгівлі, міжнародного зв'язку, а через вартість послуг провайдерів і обмеження швидкості - колись Youtube замінить телевізор чи ПК.
|
||||
|
||||
В мене відносно пізно з'явився комп'ютер, я закінчував вищу медичну освіту на якому і серед багатьох хобі, у вільний час писав статті та різні замітки в MS Word, зберігаючи їх просто до локальної теки. Але Інтернет змінив все, з його появою, нарешті я міг ділитися своїми роботами з іншими та більше того - не шукати потрібну інформацію в книжкових магазинах, де якість технічної літератури була просто водою у порівнянні з авторськими блогами; дуже скоро почав робити свої сайти і в мене почали з'являтись перші комерційні замовлення. Так, поступово став поглиблюватись в технічну сферу, яка почала займати 100% мого студентського часу, а потім й стала основною роботою.
|
||||
|
||||
Оскільки через тодішню швидкість мережі ринок е-комерсу в Україні розвивався повільно, час від часу мені траплялись замовлення на закордонному рику, де крім того, що фігурували інші суми, попиту було в рази більше. Але була одна проблема: фінансові операції з країнами пост-СНД, зокрема через популярний на заході Paypal, були не доступні. Тоді я вперше зіткнувся з якимось невидимим бар'єром, не справедливістю, що відгороджує мою країну з тими ямами на дорогах від цивілізованого світу. Тоді прийшло розуміння, що Україна перебуває в штучній ізоляції, через корупцію та "договірняки" з російською мафією, з'явився певний дух протесту до системи, а з ним - вивчення технологій, що близькі свободі по духу: зокрема - OpenSource.
|
||||
|
||||
## Децентралізовані технології
|
||||
|
||||
Одного разу, я прочитав новину про реліз Bitcoin - свого роду розрахункову систему накшталт електронної пошти, тільки для грошей. При чому, на відміну від тодішніх централізованих контор типу WebMoney (з яких також на закордонному ринку було мало толку) нова криптовалюта не мала центрального органу та не мала географічних обмежень. Це для мене стало просто з'їздом даху в плані потенційних можливостей. Але була одна проблема: вона була нікому не відомою і щоб отримати 50 доларів, доводилось пояснювати кожному замовникові як встановити гаманець, де обміняти "реал" в його країні та як переказати гроші :)
|
||||
|
||||
Тим не менше, це мало певний результат, а схожі технології, що базувались на Bittorrent - стали дружніми та цікавими, оскільки в ньому не було такого поняття як "модерація" та "злий адмін" взагалі. У ті часи з'являлось багато інших цікавих проєктів по типу Twister, ZeroNet, IPFS і т.д., які також мали на меті свободу поширення та доступу до інформації та свободи слова. Відбувся свого роду бум, тоді альтернативні, зокрема соціальні мережі отримали великий імпульс і затягнули мене своєю цікавістю в "діпвеби", де й провів багато часу на ентузіазмі, зокрема ще й тому, що інтелектуальний рівень їх користувачів був у рази вищим за "юзвірів" популярних порталів. Було чому повчитись.
|
||||
|
||||
Але пройшло більше десяти років і можна побачити, що майже всі альтернативні платформи мертві. Bitcoin, замість вільного засобу розрахунків, став чорною дірою для спекуляцій, де лох - не мамонт. Пам'ятаю єдиний магазин в Києві, де колись офлайн за біткоїн можна було купити пончик, вже мабуть закрився. Звісно, сьогодні вам продадуть пончик в іншому місці, але це не те, чим мало стати взагалі. Чому так? Давайте розглянемо технічну сторону цього питання, адже для інших сфер - є свої спеціалісти.
|
||||
|
||||
На мою думку, ахіллесовою п'ятою всіх революційних технологій, є використання ними класичних засобів зв'язку. Так, на прикладі Bitcoin, щоб підключити свій гаманець до спільного реєстру блокчейн, потрібно з'єднатись з певним сервером DNS, який надасть вам IP адреси публічних вузлів Bittorrent, через які вже можна отримати дані поточних блоків. Оскільки весь ланцюг з'єднання не включає принципово нових засобів комунікації, такі канали можуть бути повністю заблоковані, а їх провайдери - притягнуті до відповідальності, як тільки певна "революційна" технологія почне заважати централізованій економіці (будь вона легальною або корумпованою).
|
||||
|
||||
Іншим моментом децентралізованих рішень, є складна архітектура їх роботи. Оскільки децентралізовані засоби зв'язку від початку були створені для військового застосування, вони не передбачали роботи з такими об'ємами даних та кількістю користувачів, яких сьогодні вимагає цивільна сфера. Наприклад, якщо запустити сервер IPFS, можна побачити, що фонове споживання трафіку складає приблизно 1 мегабіт на секунду і це "на холостих" і при відносно малій кількості пірів у мережі - близько 400. Можна уявити, що станеться з каналом та акумулятором мобільного пристрою (де кожен пір являє собою хеш-суму) при підключенні до рою мільйонів користувачів одночасно. По цій причині, користувачі криптовалют часто користуються "легкими" гаманцями, тобто такими, які підключаються до мережі на стороні серверу, а користувачеві видають ті само порожні цифри балансу, які надає по суті звичайний банк.
|
||||
|
||||
З точки зору приватності, на мою думку, децентралізовані рішення є парадоксально найбільш вразливими, оскільки в таких мережах користувач надає свою адресу усім її учасникам. Тому якщо справа стосується публікації "чутливих" даних, то потрібно спочатку приховати адресу і вже після того підключатись. Насправді зробити це не так просто, оскільки звичайний VPN може працювати тільки для певного інтерфейсу програми, у той час як на фоні, вона також може підключатись до сторонніх сервісів, використовуючи інший протокол чи зовнішню бібліотеку службового сервісу, через білий IP. Для рядового користувача, це майже непосильне завдання, оскільки потребує окремої збірки операційної системи на певному залізі.
|
||||
|
||||
## Fediverse
|
||||
|
||||
Таким чином, еволюційно на зміну повній "децентралізації" як такої, приходять "федеративні" рішення: коли багато невеличких серверів формують одну спільну екосистему Fediverse, яку ще називають "сузір'ям". Яскравим і найбільш вдалим прикладом реалізації є соціальна мережа мікро-блогінгу Mastodon.
|
||||
|
||||
Обраний сервер, або "провайдер", тут виступає вже у якості проксі та свого роду, додатковим "фаєрволом" для користувача. Можна збитись в певні кучі по інтересам і тусити у вузьких колах однодумців, де в інших місцях вас за такі само пости виженуть або заблокують, але знову таки до тих пір, допоки адміну це подобається або його чи його хостинг-провайдера разом з вашими персональними даними не візьмуть за дупу в юрисдикції тієї країни, де він знаходиться.
|
||||
|
||||
Недоліком федеративних рішень є також відсутність будь яких гарантій зі сторони їх "диких" провайдерів, ваш контент може бути так само легко втрачено як і додано. Це знову таки, рішення "зробити сервіс нікому не потрібним, для того, щоб його не заблокували". Ну і звісно, приватні кампанії фізичних осіб рідко слідують наданим ними самими угодам обробки персональних даних користувача, на відміну від медіа холдингів США, таких як Twitter, Facebook тощо.
|
||||
|
||||
## Mesh, TOR, Onion
|
||||
|
||||
Існують різні технології тунелювання (TOR), заплутування маршрутів (Onion) та віртуальних мереж (CJDNS, Yggdrasil та інших). Всі їх об'єднує спільна риса: вам потрібно якось до них підключитись. Так, можна орендувати VPN, або ланцюг з таких, але кожен з них буде посилатись на початковий вузол, а маскування трафіку під "443" (через наприклад Shadowsocks) можна легко викрити шляхом перебору протоколів під час рукостискання (handshake) з публічним вузлом. Тому отримання таких даних - це просто "питання потреби"
|
||||
|
||||
Як варіант, можна взагалі не використовувати Інтернет і уявити собі світ, де кожен юзер роздає по Wi-Fi точку Yggdrasil, але цього мабуть ніколи не станеться. У разі гіпотетичної катастрофи, ймовірно будуть так само використовуватись стандартні протоколи IPv4/IPv6 для побудови класичних локальних мереж, допоки вони знову не з'єднаються і не утворять собою нову мережу Інтернет.
|
||||
|
||||
Ще однією стороною проблеми анонімізації, яку обіцяють технології вище - неможливість приховування такими засобами цифрового відбитку. Наразі, вже кожному доступні технології штучного інтелекту, які наочно демонструють можливості конверсії будь яких аналогових об'єктів, у нашому випадку з копірайтингом - це може бути як використання діалекту чи навіть пунктуації.
|
||||
|
||||
## Альтернативні протоколи
|
||||
|
||||
Альтернативний протокол передбачає фундаментально новий підхід в обміні інформацією, який невідомий моніторинговій стороні. Це може бути наприклад аналоговий радіо-зв'язок, що використовується в морі.
|
||||
|
||||
Тут мало що можу сказати, маю досвід перебування в окупації, де не те щоб сховатись серед іншого трафіку, але й випромінювати будь який сигнал - самовбивство. Навіть за відсутності радіо передавання, звичайний дріт чи обладнання знищується тими, хто проводить зачистки. Якщо у вас потім знайдуть взагалі будь який пристрій, якого не мало бути - про наслідки думайте самі.
|
||||
|
||||
Отже колись романтична віра в технології пост-апокаліпсису, на ділі виявилась плацебо. У форс-мажорних обставинах, ви не зможете користуватись зв'язком як таким, без ризику бути виявленим, навіть якщо це ліхтарик та азбука морзе. Тож цивільний формат зв'язку забезпечується виключно екосистемою тієї країни, де ви знаходитесь і ймовірно користуватись іншими засобами, окрім ліцензованих - не зможете.
|
||||
|
||||
### Веб протоколи
|
||||
|
||||
Щодо цивільного середовища, не так давно, відкрив для себе старі-нові Веб-протоколи, зокрема Gemini. Пам'ятаю, як задумувався про щось схоже, але було чим займатись окрім як розвивати цю думку матеріально. Але не так давно, знову наткнувся на концепцію мінімалізму, яку пропонує протокол Gemini у якості інструмента приватності. Тут немає JS, Cookies та всього того, з чим бореться Ublock та не намагається зовсім - жоден із сучасних Веб-браузерів.
|
||||
|
||||
Утім, на практиці, досить рідко відвідую Geminispace, оскільки по-перше мало україномовного контенту, в той час як англомовний мені просто не цікавий (бо спільнота живе там своїм життям, до якої мені просто наразі немає діла). З іншого боку, сторінки Geminispace всі однотипні, не зручно читати великі тексти, а щоб переглянути зображення, потрібно спочатку підвантажити, натиснувши на посилання (приватність, все таки).
|
||||
|
||||
Стосовно конфіденційності користування - це звичайний собі веб з моделлю "клієнт-сервер", з тією лише різницею, що всі колись асинхронні запити та завантаження зображень ви будете робити вручну. Такий собі формат "я знаю, на що йду" (хоча не варто забувати про DNS на шляху таких "знань")
|
||||
|
||||
## Класичний Інтернет
|
||||
|
||||
Колись так обожнюваний мною Інтернет, після вивчення базових принципів його роботи, сьогодні для мене виглядає як технологічне решето: через браузер відбувається купа фонових JavaScript звернень до третіх серверів без мого відому, Cookies, з їх імпотентними банерами на кожному сайті.
|
||||
|
||||
Частина Веб-контенту взагалі еволюціонувала у збереження десь в базах даних месенджерів по типу Телеграм, але тут окрім IP, зливається невідомо кому ще й номер телефону а також, в залежності від застосунку - гео-дані та мета дані пристрою. Я не розумію, яким чином в умовах війни, в Телеграм присутні офіційні державні агентства, зокрема такі, що функціонують на окупованих територіях, адже це просто самовбивство для потенційних громадян що там лишились але за відсутності досвіду в сфері ІТ, користуються даним інструментом за офіційними рекомендаціями.
|
||||
|
||||
## Висновки
|
||||
|
||||
Підсумовуючи сказане, на мою думку, будь який пристрій, що підключається до мережі - як не крути, є потенційною дірою. Навіть користуючись вільною операційною системою з відкритим кодом, не виключається ймовірність наявності неописаних багів, що мовчки використовуються відповідними спеціалістами. Постійно фігурують випадки контрибуцій з вразливостями, які потім спішно видаляють з репозиторіїв, але мільйони користувачів вже встигли встановити такі оновлення.
|
||||
|
||||
Конфіденційності для пристрою, підключеного до мережі Інтернет, на мою думку, просто не існує. Немає такого інструменту, що дозволить бути 100% впевненим. Приховати дані у сучасній мережі Інтернет, можна тільки не маючи жодних зв'язків з цією технологією, зробивши еволюційний крок назад, у часи палеоліту.
|
||||
|
||||
### Переосмислення
|
||||
|
||||
Будь які інструменти анонімізації, ймовірно, суперечать початковим концепціям Інтернет, а використання таких просто створює ізоляційний вакуум та обмежує доступність інформації.
|
||||
|
||||
Щодо інструментів без цензури та вільної журналістики, анонімні джерела мають мінімальну вагу, оскільки не є перевіреними. Публікація ноунейма у хащах діпвебу просто не викличе резонансу. У цій справі, як і в інших сферах - потрібна відповідальність та мужність.
|
||||
|
||||
Свобода вибору, захист персональних даних, авторського права, надання гарантованих послуг (таких як хостинг для VPN), можливість висловлювати точку зору та користування перевагами цивілізованого світу, є результатом злагодженої роботи в багатьох сферах - оборонної, дипломатичної, соціально-ініціативної. Конфіденційність, сама по собі, як функціональна одиниця - не ефективна, особливо в такому середовищі як Інтернет. Мабуть, тут вона і не потрібна.
|
||||
|
||||
Цінуймо справжню свободу, а не імітацію. Допомагаймо тим, хто її боронить!
|
||||
226
public/uk/install-aquatic-open-tracker-on-linux.gmi
Normal file
226
public/uk/install-aquatic-open-tracker-on-linux.gmi
Normal file
|
|
@ -0,0 +1,226 @@
|
|||
# Встановлення BitTorrent трекера Aquatic в Linux
|
||||
|
||||
Давно збирався підняти BitTorrent трекер відкритого типу для мережі Yggdrasil.
|
||||
|
||||
Детальніше про мережу Yggdrasil читайте тут:
|
||||
=> yggdrasil-is-network-with-distributed-routing.gmi Yggdrasil - мережа з децентралізованою маршрутизацією
|
||||
|
||||
Вже існує відомий сервер з 15-річною історією розробки OpenTracker:
|
||||
=> https://erdgeist.org/arts/software/opentracker
|
||||
|
||||
Але останнім часом, я надаю перевагу більш сучасній мові Rust, тим паче що потім планую реалізувати цією мовою додатковий веб-агрегатор на базі кешованих трекером інфо-хешів у зв'язці з бібліотекою rqbit:
|
||||
=> https://github.com/ikatson/rqbit
|
||||
|
||||
Трохи полиставши результати пошуку на GitHub, віднайшов сервер Aquatic:
|
||||
=> https://github.com/greatest-ape/aquatic
|
||||
|
||||
Він також підтримує IPv4/IPv6, протоколи UDP, HTTP, WS і так само зберігає дані в оперативній пам'яті, не зношуючи своєю роботою носій SSD. Нижче опишу покрокову інструкцію збірки, встановлення та налаштування для мережі Yggdrasil, можливо даний матеріал буде цікавий початківцям, зокрема - для використання в класичній мережі Інтернет.
|
||||
|
||||
## Підготовка системи
|
||||
|
||||
### Створення системного користувача
|
||||
|
||||
Як і для інших програм Linux, що збираються з початкового коду і запускаються через systemd, я створюю окремого системного користувача з домашньою текою, для ізоляції прав доступу:
|
||||
``` bash
|
||||
useradd -m aquatic
|
||||
```
|
||||
|
||||
### Встановлення системних залежностей
|
||||
|
||||
Програмне середовище Rust у мене розгорнуте в профілі root, куди я клоную репозиторії і засобами профілю якого проводжу збірку всіх бінарних файлів.
|
||||
Якщо в системі не встановлена інфраструктура Rust (rustc, cargo та інше) тоді вам сюди:
|
||||
=> https://rustup.rs
|
||||
|
||||
Стандартна інсталяція залежностей Rust вимагає близько 2 Гб дискового простору. Якщо ви, як і я, користуєтесь VPS - встановіть лише необхідні для роботи компілятора пакунки.
|
||||
|
||||
Для цього при першому запуску команди:
|
||||
``` bash
|
||||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
|
||||
```
|
||||
|
||||
* оберіть пункт "Customize installation"
|
||||
* замість стандартного "Profile (which tools and data to install)" вкажіть "minimal"
|
||||
|
||||
Це пропустить встановлення зайвих на сервері пакунків, що зменшить розмір до ~600 Мб.
|
||||
|
||||
У випадку використання "minimal", для збірки також важливо до-встановити глобальні залежності:
|
||||
``` bash
|
||||
apt install clang libclang-dev
|
||||
```
|
||||
* при інсталяції rustup в режимі "default", цей крок можна пропустити.
|
||||
|
||||
Якщо rustup вже встановлено, також переконаймось, що використовуються актуальні версії:
|
||||
``` bash
|
||||
rustup update
|
||||
cargo update
|
||||
```
|
||||
|
||||
### Встановлення Aquatic
|
||||
|
||||
Виконуємо наступні кроки у послідовності:
|
||||
``` bash
|
||||
su root && cd ~
|
||||
```
|
||||
* логінимось (якщо досі не root) і переходимо в домашню теку
|
||||
``` bash
|
||||
git clone https://github.com/greatest-ape/aquatic.git && cd aquatic
|
||||
```
|
||||
* клонуємо вихідний код і переходимо до теки проєкту
|
||||
``` bash
|
||||
cargo build --release -p aquatic_udp
|
||||
```
|
||||
* збираємо оптимізовані бінарні пакети aquatic_udp
|
||||
|
||||
Таким чином, бінарники будуть доступні у теці "/root/aquatic/target/release/*". Оскільки ми будемо використовувати сервіс systemd, де відсутні змінні середовища, важливо скопіювати (або залінкувати) необхідні пакети в системне розташування, де вони матимуть відповідні права на виконання:
|
||||
``` bash
|
||||
install /root/aquatic/target/release/aquatic_udp /usr/local/bin/aquatic_udp
|
||||
```
|
||||
* мені потрібен тільки сервер UDP, якщо ви хочете підняти HTTP та WS, виконайте аналогічні кроки для інших саб-крейтів;
|
||||
* тут ми використовуємо команду "install" замість "cp", оскільки вона автоматично встановлює правильні права доступу;
|
||||
* якщо не плануєте оновлення, на даному етапі можна видалити не потрібні вихідні коди.
|
||||
|
||||
### Файл конфігурації
|
||||
|
||||
Сервер Aquatic можна запускати зі стандартним набором опцій, без аргументів (отримати поточні налаштування для конфігурації сервера можна командою:
|
||||
``` bash
|
||||
aquatic_udp -p
|
||||
```
|
||||
|
||||
Оскільки мій сервер буде працювати в режимі Yggdrasil-only, як скопіюю цей вивід у спільний системний файл конфігурації командою:
|
||||
``` bash
|
||||
aquatic_udp -p > /etc/aquatic.toml
|
||||
```
|
||||
* приклад systemd нижче буде використовувати цей модифікований файл
|
||||
|
||||
Стандартна конфігурація передбачає запуск на всіх інтерфейсах і порті 3000, я ж змінюю на окрему адресу підмережі Yggdrasil і більш типовий для відкритих UDP трекерів порт 6969. Детальніше про те, як створити адресу підмережі Yggdrasil - читайте тут:
|
||||
=> http://[222:a8e4:50cd:55c:788e:b0a5:4e2f:a92c]/yggdrasil:subnet_setting
|
||||
|
||||
``` aquatic.toml
|
||||
# вимикаю IPv4, так як цей інтерфейс в Yggdrasil не обслуговується
|
||||
use_ipv4 = false
|
||||
# "[xxx:xxxx:xxxx:xxxx::fdb]" - актуальна адреса IPv6,
|
||||
# "fdb" - це імпровізований постфікс у діапазоні A-f0-9 типу "file database"
|
||||
address_ipv6 = "[xxx:xxxx:xxxx:xxxx::fdb]:6969"
|
||||
```
|
||||
|
||||
Якщо потрібен вивід публічної веб-статистики, вказуємо також:
|
||||
``` aquatic.toml
|
||||
write_html_to_file = true
|
||||
# шлях може бути іншим
|
||||
# * у цьому випадку створіть каталог командою `mkdir /var/www/aquatic`
|
||||
# * надайте відповідні права `chown aquatic:aquatic /var/www/aquatic`
|
||||
html_file_path = "/var/www/aquatic/index.html"
|
||||
```
|
||||
|
||||
В конфігурації хосту nginx додаємо наступне (не забуваємо також відкрити 80 порт):
|
||||
``` /etc/nginx/default.conf
|
||||
server {
|
||||
# актуальна адреса IPv6
|
||||
listen [xxx:xxxx:xxxx:xxxx::fdb]:80;
|
||||
server_name xxx:xxxx:xxxx:xxxx::fdb;
|
||||
|
||||
root /var/www/aquatic;
|
||||
index index.html;
|
||||
|
||||
location / {
|
||||
try_files $uri $uri/ =404;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Не забуваємо застосувати зміни:
|
||||
``` bash
|
||||
nginx -t
|
||||
systemctl reload nginx
|
||||
```
|
||||
|
||||
Інші налаштування лишаю стандартними.
|
||||
|
||||
### Налаштування Firewall
|
||||
|
||||
В системах Debian, в режимі UDP / Yggdrasil-only (трекер прийматиме та віддаватиме виключно внутрішньомережеві адреси пірів) я використовую наступне перманентне правило ufw для iptables:
|
||||
``` bash
|
||||
ufw allow from 0200::/7 to 0200::/7 port 6969 proto udp
|
||||
```
|
||||
* якщо в конфігурації вказано інший порт, використовуйте його замість 6969
|
||||
|
||||
Якщо у вас звичайний Інтернет трекер, можна просто додати дозвіл на всі вхідні типи підключень:
|
||||
``` bash
|
||||
ufw allow 6969
|
||||
```
|
||||
|
||||
Не забуваємо по аналогії відкрити порт на веб-статистику, якщо така використовується у конфігурації вище!
|
||||
|
||||
### Сервіс systemd
|
||||
|
||||
Від root створюємо новий файл конфігурації:
|
||||
``` bash
|
||||
nano /etc/systemd/system/aquatic.service
|
||||
```
|
||||
|
||||
У цьому файлі, на моєму прикладі, вказано тільки запуск сервера UDP, якщо буде потрібно, додам й інші протоколи в рамках спільного сервісу (послідовністю команд групи "exec" або додатковим скриптом). Ви можете створити для себе окремі юніти типу "aquatic_ws.service", але на мою думку це не зручно і краще адмініструвати спільною короткою командою.
|
||||
|
||||
Зміст файлу приблизно такий:
|
||||
``` /etc/systemd/system/aquatic.service
|
||||
[Unit]
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=aquatic
|
||||
Group=aquatic
|
||||
ExecStart=/usr/local/bin/aquatic_udp -c /etc/aquatic.toml
|
||||
StandardOutput=file:/home/aquatic/debug.log
|
||||
StandardError=file:/home/aquatic/error.log
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
Керування процесом відбувається наступними командами:
|
||||
|
||||
``` bash
|
||||
systemctl daemon-reload
|
||||
```
|
||||
* оновлюємо конфігурацію systemd
|
||||
``` bash
|
||||
systemctl enable aquatic
|
||||
```
|
||||
* автостарт при запуску системи
|
||||
``` bash
|
||||
systemctl start aquatic
|
||||
```
|
||||
* запуск
|
||||
|
||||
## Тестування
|
||||
|
||||
Після запуску сервісу, перевіряємо наявність активного процесу:
|
||||
``` bash
|
||||
netstat -tulpn | grep aquatic_udp
|
||||
```
|
||||
|
||||
На прикладі моєї конфігурації Yggdrasil, має бути щось типу такого:
|
||||
``` bash
|
||||
udp6 0 0 xxx:xxxx:xxxx:xxxx:6969 :::* 123456/aquatic_udp
|
||||
```
|
||||
|
||||
Також дивимось журнали:
|
||||
* /home/aquatic/debug.log
|
||||
* /home/aquatic/error.log
|
||||
|
||||
На стороні клієнта, створюємо новий торент (в qBittorrent це "Tools" -> "Torrent Creator")
|
||||
і вказуємо адресу нашого нового трекеру, після чого перевіряємо оновлення веб-статистики;
|
||||
так само, можна додати трекер до наявної роздачі.
|
||||
|
||||
В принципі, це все, якщо комусь цікаво - мій сервер розташований тут:
|
||||
```
|
||||
udp://[302:68d0:f0d5:b88d::fdb]:6969
|
||||
```
|
||||
|
||||
Веб-статистика:
|
||||
=> http://[302:68d0:f0d5:b88d::fdb]
|
||||
=> http://tracker.ygg
|
||||
|
||||
Також, на разі працюю над агрегатором Aquatic для підписок на оновлення трекеру в різних форматах:
|
||||
=> https://github.com/YGGverse/aquatic-crawler aquatic-crawler (Rust)
|
||||
252
public/uk/install-flarum-v2-on-linux.gmi
Normal file
252
public/uk/install-flarum-v2-on-linux.gmi
Normal file
|
|
@ -0,0 +1,252 @@
|
|||
# Встановлення Flarum v2 в Linux
|
||||
|
||||
Днями було засновано українську спільноту адміністраторів альтернативних мереж. У якості платформи для спілкування - обрано рушій Flarum:
|
||||
=> https://flarum.org
|
||||
|
||||
Цей матеріал - адаптована версія локальної інструкції для Debian/Linux, якщо комусь потрібно буде швидко розгорнути дану платформу, адже в документації не вказані деякі, на мою думку, важливі моменти.
|
||||
|
||||
## Системні залежності
|
||||
|
||||
``` bash
|
||||
apt install composer php-fpm\
|
||||
php-curl php-dom php-sqlite3\
|
||||
php-fileinfo php-gd php-json php-mbstring\
|
||||
php-openssl php-pdo php-tokenizer php-zip php-session
|
||||
```
|
||||
* в `apt` має вискочити нотайс з пропозицією поставити `php-common`, тому `php-dom`, `php-fileinfo` здається можна випиляти зі списку, але залишу цю команду з історії bash, як вона є.
|
||||
|
||||
## Рушій
|
||||
|
||||
> В рамках спільноти, також було створено спеціалізований форк, для роботи з локальними поштовими скриньками без DNS. Нижче описана збірка для звичайної (офіційної) версії.
|
||||
|
||||
``` bash
|
||||
cd /var/www
|
||||
```
|
||||
|
||||
``` bash
|
||||
composer create-project flarum/flarum:^2.0.0 --stability=beta
|
||||
```
|
||||
* встановлюємо через Composer
|
||||
|
||||
``` bash
|
||||
cd /var/www
|
||||
```
|
||||
* переходимо до теки проєкту
|
||||
|
||||
``` bash
|
||||
composer update
|
||||
```
|
||||
* оновлюємо реєстр залежностей PHP
|
||||
|
||||
``` bash
|
||||
php flarum install
|
||||
```
|
||||
* встановлюємо базу даних (тут створюється файл `config.php`)
|
||||
* при виконанні команди `php flarum install` і використання драйвера SQLite, важливо вказати `name.sqlite` (з розширенням)
|
||||
* назву хосту лишаємо як є (`localhost`)
|
||||
|
||||
Так як форум спільноти працює на обидві мережі Yggdrasil/Mycelium, у файлі `config.php` я вказав:
|
||||
|
||||
``` config.php
|
||||
'url' => null,
|
||||
```
|
||||
* є ще рецепт: `'url' => '//' . $_SERVER['HTTP_HOST']`, але у такому разі компіляція статики не можлива, щонайменше на версії 2 буде помилка JS, ну і якщо робити то якось так, щоб не було warning при скиданні кешу: `'url' => isset($_SERVER['HTTP_HOST']) ? '//' . $_SERVER['HTTP_HOST'] : null`
|
||||
* якщо встановити `null` то можливі проблеми з редіректами, наприклад, при виході з акаунту
|
||||
* якщо ставите форум для класичного Інтернет - просто вкажіть свій основний хост
|
||||
|
||||
Далі вийшов з цієї теки та надав права веб-серверу, згідно інструкції:
|
||||
|
||||
``` bash
|
||||
chown -R www-data:www-data /var/www/flarum
|
||||
```
|
||||
* тут треба придумати щось з групами, бо від `root` менеджер `composer` пускати не рекомендовано (наприклад, для оновлень рушія чи встановлення нових пакунків)
|
||||
|
||||
## Nginx
|
||||
|
||||
``` /etc/nginx/default
|
||||
server {
|
||||
# для спільноти 443 порт не використовується,
|
||||
# натомість є два "дзеркала" IPv6
|
||||
listen [xxx:xxxx:xxxx:xxxx::x1]:80;
|
||||
listen [xxx:xxxx:xxxx:xxxx::x2]:80;
|
||||
|
||||
server_name xxx:xxxx:xxxx:xxxx::x1 xxx:xxxx:xxxx:xxxx::x2;
|
||||
|
||||
access_log /var/log/nginx/flarum.access.log;
|
||||
root /var/www/flarum/public;
|
||||
index index.php index.html;
|
||||
|
||||
include /var/www/flarum/.nginx.conf;
|
||||
|
||||
location ~ \.php$ {
|
||||
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
|
||||
include fastcgi_params;
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
}
|
||||
}
|
||||
```
|
||||
* версію сокета PHP замініть актуальною (`php -v`)
|
||||
* шляхи `/var/www/flarum` я пишу з пам'яті, бо довго тягав локацію туди-сюди і зараз вона в мене розташована на окремому, примонтованому диску, тому перевірте відповідність у себе актуальну щоб не було конфузів
|
||||
* тут я ще думаю залочити локацію `/admin` по IP
|
||||
|
||||
## Локалізація
|
||||
|
||||
Пакети локалізації постачаються українською спільнотою Joomla-UA:
|
||||
=> https://github.com/flarum-lang/ukrainian
|
||||
* але схоже що тільки для першої версії, бо встановлення ніяк не позначилось на поточному інтерфейсі.
|
||||
|
||||
## Бекапи
|
||||
|
||||
Я зберігаю дані в SQLite, тому тут все просто:
|
||||
|
||||
``` bash
|
||||
mkdir -p /path/to/flarum/daily
|
||||
crontab -e
|
||||
@daily /usr/bin/rsync -av --delete /path/to/flarum.sqlite /path/to/flarum/daily-dir
|
||||
```
|
||||
* аватарки та інші медіа ще не вияснив де зберігаються, доповню
|
||||
|
||||
## Виявлені проблеми
|
||||
|
||||
### Швидкість
|
||||
|
||||
Рушій здивував своєю тормознутістю. Особливо в режимі дебаг. Можливо, це залежить від SSD та кількості PHP файлів Symfony, які потребують кешування препроцесору. Або ж in-memory драйвера сесій замість БД. Це питання я ще для себе вирішую. Якщо знаєте відповідь - поділіться в коментарях!
|
||||
|
||||
### Зовнішні запити
|
||||
|
||||
Згодом, в консолі були помічені зовнішні запити до кешуючих серверів:
|
||||
|
||||
```
|
||||
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://cdn.jsdelivr.net/gh/s9e/hljs-loader@1.0.36/loader.min.js. (Reason: CORS request did not succeed). Status code: (null).
|
||||
```
|
||||
|
||||
Для Веб - це "нормально", але для оверлейних мереж і спільноти, виправлено так:
|
||||
вимикаємо або вказуємо локальне дзеркало "CDN mirror address" для додатка `flarum-emoji`
|
||||
|
||||
### Тривалість сесій авторизації
|
||||
|
||||
Форум викидає користувача через відносно короткий час (120 хвилин). Рішення проблеми:
|
||||
|
||||
``` php
|
||||
// File <flarum>/extend.php
|
||||
|
||||
use Flarum\Extend;
|
||||
use Flarum\Foundation\AbstractServiceProvider;
|
||||
use Illuminate\Contracts\Config\Repository as ConfigRepository;
|
||||
|
||||
class MyServiceProvider extends AbstractServiceProvider {
|
||||
public function register () {
|
||||
$this->container->make(ConfigRepository::class)->set('session.lifetime', 43829); // In minutes. Default is 120
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
// Register extenders here to customize your forum!
|
||||
(new Extend\ServiceProvider)
|
||||
->register(MyServiceProvider::class),
|
||||
];
|
||||
```
|
||||
=> https://discuss.flarum.org/d/21562-login-session-timeout/15 є ще один приклад для старішої версії
|
||||
* UPD: згодом змінив `session.lifetime` на `session.gc_maxlifetime`
|
||||
* щоб не робити окремий файл-костиль, можна просто вказати ці опції в `/etc/php/{VERSION}/fpm/php.in` та оновити налаштування командою `systemctl restart php{VERSION}-fpm`
|
||||
|
||||
### Пошта
|
||||
|
||||
Класична електронна пошта (e-mail) - ядро системи облікових записів для цього рушія. В принципі, можна вимкнути (точніше перемкнути пересилання листів до журналу) і вручну створювати користувачів, але вони не зможуть навіть скинути свій пароль без пересилання їм коду підтвердження.
|
||||
|
||||
#### Sendmail
|
||||
|
||||
Підійде у разі, якщо ви плануєте роботу з поштою але у вас з якихось причин немає повноцінного SMTP провайдера, наприклад Google.
|
||||
|
||||
##### Postfix / SMTP
|
||||
|
||||
Нижче показано самий простий приклад, який передбачає опцію налаштування "sendmail" що вказується в адмінці. У цьому випадку, 25 порт є закритим на фаєрволі.
|
||||
|
||||
``` bash
|
||||
apt install postfix
|
||||
```
|
||||
Мій файл конфігурації `/etc/postfix/main.cf` саме для цього ресурсу виглядає так:
|
||||
|
||||
``` /etc/postfix/main.cf
|
||||
myhostname = localhost
|
||||
|
||||
smtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU)
|
||||
biff = no
|
||||
append_dot_mydomain = no
|
||||
readme_directory = no
|
||||
smtpd_use_tls=no
|
||||
compatibility_level = 3.6
|
||||
|
||||
smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated defer_unauth_destination
|
||||
|
||||
alias_maps = hash:/etc/aliases
|
||||
alias_database = hash:/etc/aliases
|
||||
|
||||
mydestination =
|
||||
relayhost =
|
||||
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
|
||||
mailbox_size_limit = 0
|
||||
recipient_delimiter = +
|
||||
inet_interfaces = all
|
||||
inet_protocols = ipv6
|
||||
|
||||
smtpd_etrn_restrictions=reject
|
||||
disable_vrfy_command = yes
|
||||
smtpd_helo_required = yes
|
||||
```
|
||||
* тут `myhostname` - ваш актуальний хост
|
||||
* `inet_protocols` можна вказати як "all" якщо планується взаємодія з Інтернет
|
||||
|
||||
##### Тестування
|
||||
|
||||
Якщо бачите повідомлення:
|
||||
> Flarum currently does not send emails. This can be due to the selected driver, or errors in its configuration.
|
||||
|
||||
то це не критично, в мене відправлення працює й з ним, головне, щоб не було помилок в поп-апах.
|
||||
|
||||
#### Варіант без пошти
|
||||
|
||||
В адмінці є варіант "log" тобто пошта буде надсилатись у файл-заглушку, з якого можна пересилати різні лінки верифікації та інші запити - руками або скриптом. Знаходиться цей журнал в `flarum/storage/logs/*.log`
|
||||
|
||||
Вимкнути самі поля форм без патчу не вийде, в адмінці доступна лише опція вимкнення реєстрацій, таким чином, користувач бачитиме помилку при надсиланні відповідного запиту (так як це зараз).
|
||||
|
||||
## Розробка
|
||||
|
||||
Так як форум спільноти має деякі не характерні фічі, що не мають сенсу для загального PR, з'явився певний досвід по розгортанню власної версії а також може стати в нагоді, якщо вам потрібно використовувати цей рушій для локальної розробки. Як і у випадку з основною документацією, тут є свої нюанси, про які в офіційній версії не сказано:
|
||||
=> https://docs.flarum.org/contributing/#setting-up-a-local-codebase
|
||||
|
||||
Якщо коротко то вам потрібен "скелет" форуму:
|
||||
=> https://github.com/flarum/flarum
|
||||
та сам фреймворк, якийсь в документації також називається "monorepo" і включає в себе різні модулі (для яких також є окремі read-only репозиторії)
|
||||
=> https://github.com/flarum/framework
|
||||
|
||||
Пакунок `framework` у даному прикладі - є вашим об'єктом модифікації, ви також можете забрати його копію з офіційного апстріму.
|
||||
|
||||
Збірка версії рушія для розробників виглядає наступним чином:
|
||||
|
||||
``` bash
|
||||
cd /var/www
|
||||
git clone https://github.com/flarum/framework.git
|
||||
cd framework
|
||||
git checkout yggverse
|
||||
cd ..
|
||||
git clone https://github.com/flarum/flarum.git
|
||||
cd flarum
|
||||
composer config repositories.0 path "/var/www/framework/*/*"
|
||||
composer config minimum-stability dev
|
||||
composer install
|
||||
php flarum install
|
||||
php flarum cache:clear
|
||||
php flarum assets:publish
|
||||
```
|
||||
* замість `php flarum install` може бути `php flarum migrate`
|
||||
|
||||
При оновленні компонентів фронт-енд, важливо (після `yarn install`) зкомпілювати оптимізовані файли дистрибутиву командою `yarn build` для подальшого встановлення в рамках компонента `flarum`. Але для цього вам треба додати такий фікс:
|
||||
=> https://github.com/YGGverse/flarum-framework/commit/b02e3b3600d5c0ff1a613590e72d91e7b9d88111
|
||||
|
||||
## Посилання
|
||||
|
||||
=> https://flarum.org Офіційний сайт рушія Flarum
|
||||
=> https://docs.flarum.org/2.x/install Офіційна документація зі встановлення Flarum v2
|
||||
=> https://github.com/YGGverse/flarum-framework/tree/yggverse Редакція фреймворку Flarum від спільноти YGGverse
|
||||
74
public/uk/install-latest-golang-version-on-debian-linux.gmi
Normal file
74
public/uk/install-latest-golang-version-on-debian-linux.gmi
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
# Встановлення останньої версії Go в Debian
|
||||
|
||||
Це коротенька інструкція для початківців, яка дозволить швидко розгорнути останню версію інфраструктури Go в Debian для збірки програм.
|
||||
|
||||
## Видалення попередньої версії
|
||||
|
||||
Спочатку перевірте, чи не встановлена певна версія Go за допомогою пакетного менеджеру:
|
||||
|
||||
```
|
||||
go version
|
||||
```
|
||||
|
||||
Якщо так, попередньо переконайтесь, що її не використовують інші програми, після чого її можна видалити із системи:
|
||||
|
||||
```
|
||||
apt remove golang
|
||||
```
|
||||
|
||||
Додатково можна перевірити наявність старих файлів та зачистити їх:
|
||||
|
||||
```
|
||||
rm -rf /usr/lib/go-ВЕРСІЯ
|
||||
```
|
||||
|
||||
## Встановлення останньої версії
|
||||
|
||||
Наступні кроки виконуються в домашній теці користувача, від якого планується запуск програми:
|
||||
|
||||
```
|
||||
cd ~
|
||||
```
|
||||
|
||||
Переходимо на сторінку завантажень Go:
|
||||
|
||||
=> https://go.dev/dl
|
||||
|
||||
і обираємо версію для потрібної архітектури:
|
||||
|
||||
```
|
||||
wget https://go.dev/dl/go1.22.1.linux-amd64.tar.gz
|
||||
```
|
||||
|
||||
Розпаковуємо архів, після чого його можна видалити:
|
||||
|
||||
```
|
||||
tar -xzf go1.22.1.linux-amd64.tar.gz
|
||||
rm go1.22.1.linux-amd64.tar.gz
|
||||
```
|
||||
|
||||
Переміщуємо файли до системної теки від "root":
|
||||
|
||||
```
|
||||
sudo mv go /usr/local/
|
||||
```
|
||||
|
||||
Створимо робочу теку Go для поточного користувача:
|
||||
|
||||
```
|
||||
mkdir ~/go
|
||||
```
|
||||
|
||||
Налаштуємо шляхи та перезавантажимо профіль:
|
||||
|
||||
```
|
||||
export PATH=$PATH:/usr/local/go/bin
|
||||
export GOPATH=~/go
|
||||
source .bashrc
|
||||
```
|
||||
|
||||
Перевіряємо результат:
|
||||
|
||||
```
|
||||
go version
|
||||
```
|
||||
50
public/uk/install-latest-rust-version-on-linux.gmi
Normal file
50
public/uk/install-latest-rust-version-on-linux.gmi
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
# Встановлення останньої версії Rust в Linux
|
||||
|
||||
Користувачі дистрибутивів з довгостроковою підтримкою, ймовірно зіткнуться з проблемою збірки програм з версією Rust, що міститься в репозиторіях.
|
||||
|
||||
Вирішується це досить просто, за допомогою утиліти Rustup:
|
||||
|
||||
=> https://www.rust-lang.org/tools/install
|
||||
|
||||
Спочатку потрібно видалити встановлені раніше версії, разом з їх залежностями.
|
||||
|
||||
Наприклад, в Debian:
|
||||
|
||||
```
|
||||
apt remove cargo rustc
|
||||
apt autoremove
|
||||
```
|
||||
|
||||
Наступні кроки виконуються від того користувача, від якого планується подальша робота з програмою.
|
||||
|
||||
Таким чином, пакети будуть стандартно встановлюватись до теки "~/.cargo"
|
||||
|
||||
Після введення наступної команди слідуємо підказкам:
|
||||
|
||||
```
|
||||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
|
||||
```
|
||||
|
||||
Оновити пакети до останньої версії можна командою:
|
||||
|
||||
```
|
||||
rustup update
|
||||
```
|
||||
|
||||
Якщо потрібно зібрати будь яку програму на більш ранній версії, наприклад "1.63" - достатньо встановити її поряд з іншою:
|
||||
|
||||
```
|
||||
rustup install 1.63
|
||||
```
|
||||
|
||||
Для збірки програми, вказуємо відповідну версію компілятора:
|
||||
|
||||
```
|
||||
cargo +1.63 build --release
|
||||
```
|
||||
|
||||
Щоб видалити встановлені таким чином "cargo", "rustc" включно з "rustup":
|
||||
|
||||
```
|
||||
rustup self uninstall
|
||||
```
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue