<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Docker - Hard Wired</title>
	<atom:link href="https://www.hardwired.dev/category/docker/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.hardwired.dev</link>
	<description></description>
	<lastBuildDate>Sat, 11 Oct 2025 04:47:46 +0000</lastBuildDate>
	<language>cs</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9</generator>

<image>
	<url>https://www.hardwired.dev/wp-content/uploads/2022/10/android-chrome-256x256-1-150x150.png</url>
	<title>Docker - Hard Wired</title>
	<link>https://www.hardwired.dev</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Outline &#8211; selfhostovaná znalostní báze</title>
		<link>https://www.hardwired.dev/2025/09/27/outline-selfhostovana-znalostni-baze/</link>
		
		<dc:creator><![CDATA[John Doe]]></dc:creator>
		<pubDate>Sat, 27 Sep 2025 19:59:00 +0000</pubDate>
				<category><![CDATA[Docker]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Různé]]></category>
		<category><![CDATA[.env]]></category>
		<category><![CDATA[autentizace]]></category>
		<category><![CDATA[databáze]]></category>
		<category><![CDATA[dex]]></category>
		<category><![CDATA[docker]]></category>
		<category><![CDATA[docker-compose]]></category>
		<category><![CDATA[Gmail]]></category>
		<category><![CDATA[HTTPS]]></category>
		<category><![CDATA[in-memory databáze]]></category>
		<category><![CDATA[konfigurace]]></category>
		<category><![CDATA[kontejnerizace]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[linxu]]></category>
		<category><![CDATA[návod]]></category>
		<category><![CDATA[nginx]]></category>
		<category><![CDATA[Nginx konfigurace]]></category>
		<category><![CDATA[notion]]></category>
		<category><![CDATA[oidc]]></category>
		<category><![CDATA[open source]]></category>
		<category><![CDATA[OpenID Connect]]></category>
		<category><![CDATA[outline]]></category>
		<category><![CDATA[postgres]]></category>
		<category><![CDATA[PostgreSQL]]></category>
		<category><![CDATA[přihlašování]]></category>
		<category><![CDATA[redis]]></category>
		<category><![CDATA[reverse-proxy]]></category>
		<category><![CDATA[reverzní proxy]]></category>
		<category><![CDATA[self-hosting]]></category>
		<category><![CDATA[selfhosted]]></category>
		<category><![CDATA[smtp]]></category>
		<category><![CDATA[SSL]]></category>
		<category><![CDATA[ubuntu]]></category>
		<category><![CDATA[YAML]]></category>
		<category><![CDATA[znalostní báze]]></category>
		<guid isPermaLink="false">https://www.hardwired.dev/?p=2836</guid>

					<description><![CDATA[<p>Takovej selfhosting Notionu bez fancy tabulek. Outline je open-source nástroj pro tvorbu a správu interní dokumentace a znalostních bází. Použité &#62;&#62;&#62;</p>
<p>The post <a href="https://www.hardwired.dev/2025/09/27/outline-selfhostovana-znalostni-baze/">Outline – selfhostovaná znalostní báze</a> first appeared on <a href="https://www.hardwired.dev">Hard Wired</a>.</p>]]></description>
										<content:encoded><![CDATA[<div id="bsf_rt_marker"></div><p>Takovej selfhosting Notionu bez fancy tabulek.<br />
<a href="https://www.getoutline.com">Outline</a> je open-source nástroj pro tvorbu a správu interní dokumentace a znalostních bází.</p>
<p><span id="more-2836"></span></p>
<h2>Použité technologie</h2>
<h3>Nginx</h3>
<p>Nginx je výkonný webový server a reverzní proxy, který se používá pro obsluhu statického obsahu, směrování požadavků na backend služby a vyvažování zátěže. Je známý svou rychlostí, nízkou spotřebou paměti a spolehlivostí při vysoké zátěži.</p>
<h3>Outline</h3>
<p><a href="https://www.getoutline.com">Outline</a> je open-source nástroj pro tvorbu a správu interní dokumentace a znalostních bází. Poskytuje jednoduché a přehledné uživatelské rozhraní pro týmovou spolupráci, verzování a rychlé vyhledávání obsahu.</p>
<h3>Dex</h3>
<p><a href="https://dexidp.io">Dex</a> je open-source identitní služba, která funguje jako „OpenID Connect“ provider. Slouží k centralizovanému ověřování uživatelů a umožňuje propojit různé aplikace s externími identity providery (např. Google, GitHub nebo LDAP).</p>
<h3>Postgres</h3>
<p>PostgreSQL (Postgres) je pokročilý open-source relační databázový systém. Nabízí podporu pro komplexní dotazy, transakce, indexy, JSON data a rozšiřitelnost pomocí vlastních funkcí, čímž se hodí pro širokou škálu aplikací od menších po enterprise řešení.</p>
<h3>Redis</h3>
<p>Redis je in-memory databáze a cache systém, který umožňuje velmi rychlý přístup k datům. Často se používá pro ukládání relací, front, výsledků výpočtů nebo jako prostředník pro komunikaci mezi službami díky podpoře publikace a odběru zpráv (pub/sub).</p>
<h3>Docker / Docker Compose</h3>
<p>Docker je platforma pro kontejnerizaci aplikací, která umožňuje spouštět software izolovaně s veškerými závislostmi. Docker Compose pak usnadňuje definování a správu vícekontejnerových aplikací pomocí jednoduchého konfiguračního souboru.</p>
<h2>Diagram</h2>
<p><img decoding="async" src="https://www.hardwired.dev/wp-content/uploads/2025/09/diagram.avif" alt="" /></p>
<h2>Postřehy</h2>
<h3>Outline</h3>
<p>Outline neumožňuje přihlašování pomocí uživatelského jména a hesla, což je poněkud nepříjemné. Musí se nakonfigurovat jedna z podporovaných služeb. Aplikace umí pracovat se Slack identitami, Google identitami a dalšími poskytovateli. Pokud nemůžete použít žádnou z těchto služeb, je tam naštěstí možnost Magic Link via Email. Je to sice nepříjemné, ale funkční řešení. Pokaždé, když se chcete přihlásit, pošle vám aplikace email s přihlašovacím odkazem. V mém setupu jsem se rozhodl použít Dex jako OIDC službu, přes kterou se mohu přihlašovat pomocí emailu a hesla.</p>
<h3>Dex</h3>
<p><a href="https://dexidp.io">Dex</a> je velmi minimalistický, takže nemá webové rozhraní. Navíc jeho dokumentace je hodně nekvalitní. Nejjednodušším způsobem, jak vše rozchodit, je přidat statického klienta a uživatele přímo do konfiguračního souboru. Musíte si ale vytvořit bcrypt hashovaná hesla. Vycházel jsem z tohoto <a href="https://mrkaran.dev/posts/setting-outline/">návodu</a>.</p>
<h3>SMTP</h3>
<p>Aby fungovalo odesílání emailů, je potřeba nakonfigurovat SMTP server. Pokud žádný po ruce nemáte, můžete použít váš Gmail účet. V nastavení Gmailu se musí vytvořit aplikační klíč, který se pak vloží do .env souboru do SMTP sekce.</p>
<h2>Setup</h2>
<h3>.env</h3>
<pre><code class="language-ini">URL=https://outline.&lt;domain.com&gt;
PORT=3050
WEB_CONCURRENCY=1
SECRET_KEY=&lt;secret key&gt;
UTILS_SECRET=&lt;utils secret&gt;
DATABASE_URL=postgres://outline:&lt;db password&gt;@outline-postgres:5432/outline
PGSSLMODE=disable

POSTGRES_USER=outline
POSTGRES_PASSWORD=&lt;db password&gt;
POSTGRES_DB=outline

REDIS_URL=redis://outline-redis:6379

FILE_STORAGE=local

FORCE_HTTPS=true

OIDC_CLIENT_ID=outline
OIDC_CLIENT_SECRET=&lt;oidc client secret&gt;
OIDC_AUTH_URI=https://auth.&lt;domain.com&gt;/dex/auth
OIDC_TOKEN_URI=http://dex:5556/dex/token
OIDC_USERINFO_URI=http://dex:5556/dex/userinfo
OIDC_USERNAME_CLAIM=email
OIDC_DISPLAY_NAME=OIDC Provider
OIDC_SCOPES=openid profile email

SMTP_SERVICE=gmail
SMTP_USERNAME=&lt;you&gt;@gmail.com
SMTP_PASSWORD=&quot;&lt;app code&gt;&quot;
SMTP_FROM_EMAIL=&lt;you&gt;@gmail.com

RATE_LIMITER_ENABLED=true
RATE_LIMITER_REQUESTS=1000
RATE_LIMITER_DURATION_WINDOW=60

ENABLE_UPDATES=true
DEBUG=http
LOG_LEVEL=info</code></pre>
<h3>DEX Config (config.yaml)</h3>
<pre><code class="language-yaml">issuer: https://auth.&lt;domain.com&gt;/dex

storage:
  type: sqlite3
  config:
    file: /var/dex/dex.db

web:
  http: 0.0.0.0:5556

staticClients:
  - id: outline
    redirectURIs:
      - &quot;https://outline.&lt;domain.com&gt;/auth/oidc.callback&quot;
    name: &quot;Knowledge Base&quot;
    secret: &lt;oidc client secret&gt;

oauth2:
  skipApprovalScreen: true

enablePasswordDB: true

staticPasswords:
  # Admin
  - email: &quot;&lt;admin&gt;@gmail.com&quot;
    hash: &quot;&lt;bcrypt password hash&gt;&quot;
    username: &quot;admin&quot;
    userID: &quot;admin-001&quot;

  - email: &quot;&lt;user&gt;@gmail.com&quot;
    hash: &quot;&lt;bcript password hash&gt;&quot;
    username: &quot;user&quot;
    userID: &quot;user-001&quot;

# Pro debug
logger:
  level: &quot;info&quot;
  format: &quot;text&quot;</code></pre>
<h3>Docker Compose</h3>
<pre><code class="language-yaml">services:
  outline:
    image: docker.getoutline.com/outlinewiki/outline:latest
    env_file: ./.env
    ports:
      - &quot;3050:3050&quot;
    expose:
      - &quot;3050&quot;
    volumes:
      - storage-data:/var/lib/outline/data
    depends_on:
      - outline-postgres
      - outline-redis

  outline-redis:
    image: redis
    env_file: ./.env
    expose:
      - &quot;6379&quot;
    volumes:
      - ./redis.conf:/redis.conf
    command: [&quot;redis-server&quot;, &quot;/redis.conf&quot;]
    healthcheck:
      test: [&quot;CMD&quot;, &quot;redis-cli&quot;, &quot;ping&quot;]
      interval: 10s
      timeout: 30s
      retries: 3

  outline-postgres:
    image: postgres
    env_file: ./.env
    expose:
      - &quot;5432&quot;
    volumes:
      - database-data:/var/lib/postgresql/data
    healthcheck:
      test: [&quot;CMD&quot;, &quot;pg_isready&quot;, &quot;-d&quot;, &quot;outline&quot;, &quot;-U&quot;, &quot;user&quot;]
      interval: 30s
      timeout: 20s
      retries: 3

  dex:
    image: dexidp/dex:v2.37.0
    ports:
      - &quot;5556:5556&quot;  # Vystaveno pro nginx proxy
    expose:
      - &quot;5556&quot;
    volumes:
      - ./dex-config:/etc/dex:ro  # Read-only mount konfigurace
      - dex-data:/var/dex         # Persistentni SQLite databáze
    command: [&quot;dex&quot;, &quot;serve&quot;, &quot;/etc/dex/config.yaml&quot;]
    healthcheck:
      test: [&quot;CMD&quot;, &quot;wget&quot;, &quot;--no-verbose&quot;, &quot;--tries=1&quot;, &quot;--spider&quot;, &quot;http://localhost:5556/dex/healthz&quot;]
      interval: 30s
      timeout: 10s
      retries: 3
    restart: unless-stopped

volumes:
  storage-data:
  database-data:
  dex-data:</code></pre>
<h3>Nginx</h3>
<h4>auth.<domain.com></h4>
<pre><code class="language-nginx">server {
    listen 80;
    server_name auth.&lt;domain.com&gt;;

    # P┼Öesm─Ťrov├ín├ş HTTP na HTTPS
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    server_name auth.&lt;domain.com&gt;;

    # SSL certifik├íty (upravte cestu podle va┼í├ş konfigurace)
    ssl_certificate /etc/nginx/ssl/&lt;domain.com&gt;/fullchain.pem;
    ssl_certificate_key /etc/nginx/ssl/&lt;domain.com&gt;/privkey.pem;

    # SSL konfigurace
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384;
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m;

    # Proxy nastaven├ş pro Home Assistant
    location / {
        proxy_pass http://&lt;service ip&gt;:5556;
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection &quot;upgrade&quot;;

        # Timeout nastaven├ş
        proxy_connect_timeout 60s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;

        # Buffering nastaven├ş
        proxy_buffering off;
        proxy_request_buffering off;
    }

    # Logov├ín├ş
    access_log /var/log/nginx/auth.&lt;domain.com&gt;.access.log;
    error_log /var/log/nginx/auth.&lt;domain.com&gt;.error.log;
}</code></pre>
<h4>outline.<domain.com></h4>
<pre><code class="language-nginx">server {
    listen 80;
    server_name outline.&lt;domain.com&gt;;

    # P┼Öesm─Ťrov├ín├ş HTTP na HTTPS
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    server_name outline.&lt;domain.com&gt;;

    # SSL certifik├íty (upravte cestu podle va┼í├ş konfigurace)
    ssl_certificate /etc/nginx/ssl/&lt;domain.com&gt;/fullchain.pem;
    ssl_certificate_key /etc/nginx/ssl/&lt;domain.com&gt;/privkey.pem;

    # SSL konfigurace
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384;
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m;

    # Proxy nastaven├ş pro Home Assistant
    location / {
        proxy_pass http://&lt;service ip&gt;:3050;
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection &quot;upgrade&quot;;

        # Timeout nastaven├ş
        proxy_connect_timeout 60s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;

        # Buffering nastaven├ş
        proxy_buffering off;
        proxy_request_buffering off;
    }

    # Logov├ín├ş
    access_log /var/log/nginx/outline.&lt;domain.com&gt;.access.log;
    error_log /var/log/nginx/outline.&lt;domain.com&gt;.error.log;
}</code></pre>

<div class="twitter-share"><a href="https://twitter.com/intent/tweet?url=https%3A%2F%2Fwww.hardwired.dev%2F2025%2F09%2F27%2Foutline-selfhostovana-znalostni-baze%2F&#038;via=hessevalentino" class="twitter-share-button">Tweet</a></div><p>The post <a href="https://www.hardwired.dev/2025/09/27/outline-selfhostovana-znalostni-baze/">Outline – selfhostovaná znalostní báze</a> first appeared on <a href="https://www.hardwired.dev">Hard Wired</a>.</p>]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Gitea a první soukromý repozitář</title>
		<link>https://www.hardwired.dev/2024/09/16/gitea-a-prvni-soukromy-repozitar/</link>
		
		<dc:creator><![CDATA[John Doe]]></dc:creator>
		<pubDate>Sun, 15 Sep 2024 22:15:31 +0000</pubDate>
				<category><![CDATA[Docker]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[docker]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[gitea]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[repository]]></category>
		<category><![CDATA[self-hosted]]></category>
		<category><![CDATA[ssh]]></category>
		<category><![CDATA[windows]]></category>
		<guid isPermaLink="false">https://www.hardwired.dev/?p=2348</guid>

					<description><![CDATA[<p>Článek navazuje na Gitea v Dockeru s daty na Synology a Gitea na veřejné subdoméně. Tentokrát si ukážeme, jak vytvořit &#62;&#62;&#62;</p>
<p>The post <a href="https://www.hardwired.dev/2024/09/16/gitea-a-prvni-soukromy-repozitar/">Gitea a první soukromý repozitář</a> first appeared on <a href="https://www.hardwired.dev">Hard Wired</a>.</p>]]></description>
										<content:encoded><![CDATA[<div id="bsf_rt_marker"></div><p>Článek navazuje na <a href="https://www.hardwired.dev/2024/09/14/gitea-v-dockeru-s-daty-na-synology/">Gitea v Dockeru s daty na Synology</a> a <a href="https://www.hardwired.dev/2024/09/15/gitea-na-verejne-subdomene/">Gitea na veřejné subdoméně</a>. Tentokrát si ukážeme, jak vytvořit nový soukromý repozitář a posílat do něj změny.</p>
<h1>Předpoklady</h1>
<ul>
<li>Máme funkční Giteu na vlastní subdoméně, do které se dokážeme přihlásit</li>
<li>Byly provedeny všechny kroky z předchozích návodů</li>
<li>Článek se zaměřuje na Windows ale na Linuxu to bude to samé nebo hodně podobné</li>
<li>Na počítači máme funkční SSH a <a href="https://git-scm.com/">GIT</a>.</li>
</ul>
<h1>Vytvoření soukromého repozitáře</h1>
<p>Přihlásíme se do naší Gitey. <code>Pluskem</code> zvolíme nový repozitář. Zadáme název repozitáře, <code>soukromy-repo-na-smazani</code>. Vybereme <code>Nastavit repozitář jako soukromý</code> a potvrdíme. Vytvoří se prázdný repozitář.</p>
<h1>Vytvoření SSH klíče</h1>
<p>Pro komunikaci s repozitářem budeme používat <a href="https://cs.wikipedia.org/wiki/Secure_Shell">SSH</a>. Budeme muset vytvořit pár klíčů, soukromý a veřejný. Soukromý bude u nás na počítači a veřejný budeme nahrajeme k repozitáři, jako přístupový.</p>
<p>Ujistíme se že v <code>c:\Users\&lt;username&gt;</code> máme složku <code>.ssh</code>. Poté v terminálu zadáme příkaz na vygenerování klíče pro přístup do Gitea. </p>
<p><code>ssh-keygen -t rsa -b 4096 -C &quot;&lt;váš email&gt;&quot; -f ~/.ssh/gitea-example-com</code></p>
<p>To ve složce <code>.ssh</code> vytvoří dva soubory. <code>gitea-example-com</code> a <code>gitea-example-com.pub</code>. Ten druhý musíme nahrát k repozitáři.</p>
<h1>Přidání klíče do Gitea repozitáře</h1>
<p>Otevřeme si repozitář. <code>Nastavení &gt; Klíče pro nasazení &gt; Přidat klič pro nasazení</code>. Pojmenujeme si ho, například <code>Domácí klíč</code>. A obsah <code>gitea-example-com.pub</code> zkopírujeme do pole <code>Obsah</code>. Nesmíme zapomenout zaškrtnout volbu <code>Povolit zápis</code> a potvrdit.</p>
<h1>Nastavení SSH na počítači</h1>
<p>Pokud ve složce <code>c:\Users\&lt;username&gt;\.ssh</code> nemáte soubor <code>config</code>, vytvořte ho a přidejte následující.</p>
<pre><code>Host gitea.example.com
  HostName gitea.example.com
  User git
  Port 222
  IdentityFile c:\Users\&lt;username&gt;\.ssh\gitea-example-com
  IdentitiesOnly yes</code></pre>
<p>Pro hosta <code>gitea.example.com</code> se nastaví odpovídající <code>host name</code>, <code>uživatel</code>, <code>port</code> pro připojení a <code>cesta k privátnímu klíči</code>. Volba <code>IdentitiesOnly</code> zajistí, že pro konkrétního hosta se použijí parametry, které jsou nastaveny.</p>
<h1>Připojení repozitáře</h1>
<p>Buď můžete připojit už existující repozitář z vašeho počítače, nebo vytvoříte nový. Vytvoříme nový.</p>
<p>Vytvořte složku kde bude nový repozitář. Obecně se pojmenuje názvem repozitáře co jsme vytvořili na naší Gitea.</p>
<pre><code class="language-shell">mkdir soukromy-repo-na-smazani</code></pre>
<p>Přesuneme se do něj.</p>
<pre><code class="language-shell">cd soukromy-repo-na-smazani</code></pre>
<p>Inicializujeme prázdný repozitář.</p>
<pre><code class="language-shell">git init</code></pre>
<p>Vytvoříme první soubor <code>README.md</code>.</p>
<pre><code class="language-shell">touch README.md</code></pre>
<p>Vytvoříme hlavní větev <code>main</code>.</p>
<pre><code class="language-shell">git checkout -b main</code></pre>
<p>Přidáme soubor <code>README.md</code> do <code>git</code> repozitáře.</p>
<pre><code class="language-shell">git add README.md</code></pre>
<p>Vytvoříme první <code>commit</code>.</p>
<pre><code class="language-shell">git commit -m &quot;První commit&quot;</code></pre>
<p>Napojíme náš repozitář z Gitea.</p>
<pre><code class="language-shell">git remote add origin git@gitea.example.com:&lt;gitea username&gt;/soukromy-repo-na-smazani.git</code></pre>
<p>Odešleme změny do vzdáleného repozitáře.</p>
<pre><code class="language-shell">git push -u origin main</code></pre>
<p>Když se nyní podíváme do repozitáře na <code>gitea.example.com</code>, uvidíme náš první <code>commit</code>.</p>

<div class="twitter-share"><a href="https://twitter.com/intent/tweet?url=https%3A%2F%2Fwww.hardwired.dev%2F2024%2F09%2F16%2Fgitea-a-prvni-soukromy-repozitar%2F&#038;via=hessevalentino" class="twitter-share-button">Tweet</a></div><p>The post <a href="https://www.hardwired.dev/2024/09/16/gitea-a-prvni-soukromy-repozitar/">Gitea a první soukromý repozitář</a> first appeared on <a href="https://www.hardwired.dev">Hard Wired</a>.</p>]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Gitea na veřejné subdoméně</title>
		<link>https://www.hardwired.dev/2024/09/15/gitea-na-verejne-subdomene/</link>
		
		<dc:creator><![CDATA[John Doe]]></dc:creator>
		<pubDate>Sun, 15 Sep 2024 18:55:58 +0000</pubDate>
				<category><![CDATA[Docker]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[container]]></category>
		<category><![CDATA[docker]]></category>
		<category><![CDATA[domain]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[gitea]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[nginx]]></category>
		<category><![CDATA[portainer]]></category>
		<category><![CDATA[reverse-proxy]]></category>
		<category><![CDATA[self-hosted]]></category>
		<category><![CDATA[subdomain]]></category>
		<guid isPermaLink="false">https://www.hardwired.dev/?p=2345</guid>

					<description><![CDATA[<p>Volné pokračování Gitea v Dockeru s daty na Synology. Tentokrát nastavíme aby nám naše self-hostovaná Gitea jela na naší veřejné &#62;&#62;&#62;</p>
<p>The post <a href="https://www.hardwired.dev/2024/09/15/gitea-na-verejne-subdomene/">Gitea na veřejné subdoméně</a> first appeared on <a href="https://www.hardwired.dev">Hard Wired</a>.</p>]]></description>
										<content:encoded><![CDATA[<div id="bsf_rt_marker"></div><p>Volné pokračování <a href="https://www.hardwired.dev/2024/09/14/gitea-v-dockeru-s-daty-na-synology/">Gitea v Dockeru s daty na Synology</a>. Tentokrát nastavíme aby nám naše self-hostovaná <a href="https://about.gitea.com/">Gitea</a> jela na naší veřejné doméně.</p>
<h1>Předpoklady</h1>
<ul>
<li>Máme nainstalovanou Giteu podle předchozího návodu.</li>
<li>Máme koupenou vlastní doménu. (pro tutoriál to bude <code>example.com</code>)</li>
<li>Používáme <a href="https://nginx.org/en/">Nginx</a> jako <a href="https://en.wikipedia.org/wiki/Reverse_proxy">reverzní proxy</a>.</li>
<li>Máme přistup do routeru nebo možnost přesměrovávat porty.</li>
<li>Už jste Giteu jednou spustili a nastavili admin účet.</li>
</ul>
<h1>Nastavení reverzní proxy</h1>
<p>Vytvoříme soubor <code>gitea.example.com</code>.</p>
<pre><code class="language-shell">nano /etc/nginx/sites-available/gitea.example.com</code></pre>
<pre><code>server {
    listen 80;
    server_name gitea.example.com;

    location / {
        return 301 https://$host$request_uri;
    }
}

server {
    listen 443 ssl;
    server_name gitea.example.com;

    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

    location / {
        proxy_pass http://<ip adresa serveru s Gitea>:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}</code></pre>
<p>Při zadání <code>gitea.example.com</code> budou všechny požadavky přesměrovávány na server, kde sedí Gitea a naslouchá na portu 3000. Také se automaticky provede přesměrování z HTTP na HTTPS.</p>
<p>Certifikáty jsou pomocí <a href="https://letsencrypt.org/getting-started/">Let's Encrypt</a> a <a href="https://certbot.eff.org/">Certbot</a>, ale to je na jiný návod. <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
<p>Poté je potřeba dostat <a href="https://cs.wikipedia.org/wiki/Symbolick%C3%BD_odkaz">symlink</a> do <code>/etc/nginx/sites-enabled</code>.</p>
<pre><code class="language-shell">sudo ln -s /etc/nginx/sites-available/gitea.example.com /etc/nginx/sites-enabled/</code></pre>
<p>Pak je dobré zkontrolovat, jestli Nginx naši novou konfiguraci vezme za svou.</p>
<pre><code class="language-shell">sudo nginx -t</code></pre>
<p>Jestli je vše OK, tak bude potřeba Nginx restartovat.</p>
<pre><code class="language-shell">sudo systemctl restart nginx</code></pre>
<p>Od teď bude <code>gitea.example.com</code> směrovat na naši Giteu.</p>
<h1>Nastavení Gitea</h1>
<p>Předpoklad je, že Gitea běží v kontejneru. Musíme upravit nastavení. Do <a href="https://www.docker.com/resources/what-container/">Docker kontejneru</a> se můžete dostat pomocí příkazové řádky <code>docker exec -it &lt;container_name_or_id&gt; /bin/bash</code>. Pokud máte rozchozený <a href="https://www.portainer.io/">Portainer</a>, stačí v něm kliknout na ikonku shellu a připojíte se do kontejneru jako <code>root</code>.</p>
<p>Po připojení do kontejneru bude pravděpodobně jako uživatel <code>root</code>. Gitea (v závislosti na typu image) má data uložena v <code>/data</code>. Ale jako uživatel <code>git</code>. Proto než začnete něco měnit, tak je dobré se přepnout za uživatele <code>git</code>. To provedete pomocí <code>su git</code>.</p>
<p>Bude potřeba udělat pár úprav v souboru <code>app.ini</code>, ten se nachází v <code>/data/gitea/conf</code>. (v Gitea kontejneru je dostupný editor <a href="https://www.atmos.albany.edu/daes/atmclasses/atm350/vi_cheat_sheet.pdf">VI</a>)</p>
<pre><code class="language-ini">DOMIAN = gitea.example.com
SSH_DOMAIN = gitea.example.com
ROOT_URL = https://gitea.example.com</code></pre>
<p>Tím nastavíme Giteu na naši doménu.</p>
<p>Je předpoklad, že je to soukromý git server, takže nechceme aby se tam mohli lidé samovolně registrovat. Takže je potřeba vypnout registrace. </p>
<pre><code class="language-ini">DISABLE_REGISTRATIONS = true</code></pre>
<p>Poté je potřeba kontejner restartovat.</p>
<h1>Přesměrování portů</h1>
<p>Gitea cotainer (pokud jste to nezměnili) propaguje porty 3000 (web) a 222 (ssh). Proto je potřeba zajistit aby byl port 222 zvenku dostupný a přesměrovával na server kde Gitea sedí. Jestli máte domácí router který sedí na veřejné IP adrese tak provedete přesměrování portů na něm.</p>
<h1>Závěr</h1>
<p>Existují ještě další nastavení, ale po těchto pár krocích by už měla Gitea fungovat na vaší doméně.</p>

<div class="twitter-share"><a href="https://twitter.com/intent/tweet?url=https%3A%2F%2Fwww.hardwired.dev%2F2024%2F09%2F15%2Fgitea-na-verejne-subdomene%2F&#038;via=hessevalentino" class="twitter-share-button">Tweet</a></div><p>The post <a href="https://www.hardwired.dev/2024/09/15/gitea-na-verejne-subdomene/">Gitea na veřejné subdoméně</a> first appeared on <a href="https://www.hardwired.dev">Hard Wired</a>.</p>]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Gitea v Dockeru s daty na Synology</title>
		<link>https://www.hardwired.dev/2024/09/14/gitea-v-dockeru-s-daty-na-synology/</link>
		
		<dc:creator><![CDATA[John Doe]]></dc:creator>
		<pubDate>Fri, 13 Sep 2024 22:39:52 +0000</pubDate>
				<category><![CDATA[Docker]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[docker]]></category>
		<category><![CDATA[docker-compose]]></category>
		<category><![CDATA[gitea]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[nfs]]></category>
		<category><![CDATA[postgres]]></category>
		<category><![CDATA[synology]]></category>
		<guid isPermaLink="false">https://www.hardwired.dev/?p=2336</guid>

					<description><![CDATA[<p>Gitea je self-hostovaná varianta Bitbucketu nebo GitHubu. V následujícím krátkém návodu se podíváme jak nainstalovat Giteu pomocí Dockeru a ukládat &#62;&#62;&#62;</p>
<p>The post <a href="https://www.hardwired.dev/2024/09/14/gitea-v-dockeru-s-daty-na-synology/">Gitea v Dockeru s daty na Synology</a> first appeared on <a href="https://www.hardwired.dev">Hard Wired</a>.</p>]]></description>
										<content:encoded><![CDATA[<div id="bsf_rt_marker"></div><p><a href="https://about.gitea.com/">Gitea</a> je self-hostovaná varianta <a href="https://bitbucket.org/">Bitbucketu</a> nebo <a href="https://github.com/">GitHubu</a>. V následujícím krátkém návodu se podíváme jak nainstalovat Giteu pomocí <a href="https://www.docker.com/">Dockeru</a> a ukládat data na <a href="https://www.synology.com/en-us">Synology NAS</a>.</p>
<h1>Prerekvizity</h1>
<ul>
<li>Nainstalovaný a nastavený Docker</li>
<li>Nainstalovaný a nastavený Synology NAS</li>
</ul>
<h1>Myšlenka</h1>
<p>Pro spuštění Gitea serveru použijeme <a href="https://docs.docker.com/compose/">docker compose</a>. Gitea bude používat <a href="https://www.postgresql.org/">PostgreSQL</a> databázi. Pro ukládání dat jak pro Giteu, tak i pro Postgres, použijeme <a href="https://docs.docker.com/engine/storage/volumes/">docker volumes</a>. <code>Docker volumes</code> nebudou lokální, ale přes protokol <a href="https://cs.wikipedia.org/wiki/Network_File_System">NFS</a> budou směřovat na Synology NAS.</p>
<p>Pro potřeby tutoriálu bude mít server IP adresu <code>192.168.10.1</code> a Synology NAS <code>192.168.10.2</code>.</p>
<h1>Nastavení Synology</h1>
<p><code>Ovládací panel</code> &gt; <code>Souborové služby</code> &gt; <code>NFS</code> povolte službu <code>NFS</code>.</p>
<p><code>Ovládací panel</code> &gt; <code>Sdílená složka</code> &gt; <code>Vytvoření sdílené složky</code>. Název <code>docker-volumes</code>. Nepřiřazujeme oprávnění pro uživatele nebo skupiny.</p>
<p>Klikneme na složku <code>docker-volumes</code> a zvolíme upravit. Poté <code>Oprávnění NFS</code>. Klikneme na tlačítko <code>Vytvořit</code>. Do pole <code>Název hostitele nebo IP adresa</code> vložíme IP adresu našeho serveru, tedy <code>192.168.10.1</code>. Tím umožníme našemu serveru přístup k této složce. Dále nastavíme:</p>
<ul>
<li>Oprávnění: <code>Čtení/Zápis</code></li>
<li>Squash: <code>Žádné mapování</code></li>
<li>Zabezpečení: <code>sys</code></li>
<li>Povolit asynchronní</li>
<li>Povolit připojení z portů bez oprávnění (porty vyšší než 1024)</li>
<li>Umožňuje uživatelům přístup k připojeným podsložkám</li>
</ul>
<p>A uložíme.</p>
<p>Poté otevřeme <code>File Station</code> a v naší složce <code>docker-volumes</code> vytvoříme následující podsložky:</p>
<ul>
<li><code>gitea-data</code></li>
<li><code>gitea-postgres</code></li>
</ul>
<p>To je na Synology vše.</p>
<h1>docker-compose.yaml</h1>
<p>Konfigurační soubor vytvoří síť <code>gitea</code> kde na sebe uvidí kontejnery <code>gitea</code> a <code>gitea-db</code>. Vytvoří <code>dva volumes</code> a pomocí protokolu NFS je nasměruje na námi sdílenou složku v Synology NAS.</p>
<p>Docker-compose soubor můžeme spustit pomocí <code>docker-compose up -d</code>. Pokud máte na serveru nainstalovaný a spuštěný <a href="https://www.portainer.io/">Portainer</a>, tak jde <code>docker-compose konfigurace</code> spustit jako <a href="https://docs.portainer.io/user/docker/stacks">stack</a>.</p>
<p>Webové rozhraní poté bude přístupné na <code>http://192.168.10.1:3000</code>.</p>
<pre><code class="language-yaml">networks:
  gitea:

volumes:
  gitea-data:
    driver: local
    driver_opts:
      type: nfs
      o: addr=192.168.1.251,rw
      device: ":/volume1/docker-volumes/gitea-data"

  gitea-postgres:
    driver: local
    driver_opts:
      type: nfs
      o: addr=192.168.1.251,rw
      device: ":/volume1/docker-volumes/gitea-postgres"

services:
  server:
    image: gitea/gitea:latest
    container_name: gitea
    environment:
      - USER_UID=1000
      - USER_GID=1000
      - GITEA__database__DB_TYPE=postgres
      - GITEA__database__HOST=gitea-db:5432
      - GITEA__database__NAME=gitea
      - GITEA__database__USER=gitea
      - GITEA__database__PASSWD=supersecretpassword
    restart: always
    networks:
      - gitea
    volumes:
      - gitea-data:/data
      - /etc/timezone:/etc/timezone:ro
      - /etc/localtime:/etc/localtime:ro
    ports:
      - "3000:3000"
      - "222:22"
    depends_on:
      - gitea-db

  gitea-db:
    image: postgres:16
    container_name: gitea-db
    restart: always
    environment:
      - POSTGRES_USER=gitea
      - POSTGRES_PASSWORD=supersecretpassword
      - POSTGRES_DB=gitea
    networks:
      - gitea
    volumes:
      - gitea-postgres:/var/lib/postgresql/data</code></pre>

<div class="twitter-share"><a href="https://twitter.com/intent/tweet?url=https%3A%2F%2Fwww.hardwired.dev%2F2024%2F09%2F14%2Fgitea-v-dockeru-s-daty-na-synology%2F&#038;via=hessevalentino" class="twitter-share-button">Tweet</a></div><p>The post <a href="https://www.hardwired.dev/2024/09/14/gitea-v-dockeru-s-daty-na-synology/">Gitea v Dockeru s daty na Synology</a> first appeared on <a href="https://www.hardwired.dev">Hard Wired</a>.</p>]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>The Calamity</title>
		<link>https://www.hardwired.dev/2023/12/26/the-calamity/</link>
		
		<dc:creator><![CDATA[Kosieh Barter]]></dc:creator>
		<pubDate>Tue, 26 Dec 2023 19:05:13 +0000</pubDate>
				<category><![CDATA[3D Tisk]]></category>
		<category><![CDATA[Arduino]]></category>
		<category><![CDATA[Docker]]></category>
		<category><![CDATA[Hardware]]></category>
		<category><![CDATA[Linux]]></category>
		<guid isPermaLink="false">https://www.hardwired.dev/?p=1875</guid>

					<description><![CDATA[<p>Grammar detailists beware. Hacky carky chybi. Jsem sice rodily cech, ale spousta textu moji rukou budiz v jazyce anglickem. Je &#62;&#62;&#62;</p>
<p>The post <a href="https://www.hardwired.dev/2023/12/26/the-calamity/">The Calamity</a> first appeared on <a href="https://www.hardwired.dev">Hard Wired</a>.</p>]]></description>
										<content:encoded><![CDATA[<div id="bsf_rt_marker"></div><h2>Grammar detailists beware.</h2>
<blockquote>
<p>Hacky carky chybi. Jsem sice rodily cech, ale spousta textu moji rukou budiz v jazyce anglickem. Je treba brati na zřetel autorovu deformaci profesnim prostredim.</p>
</blockquote>
<h3>Na zacatek...</h3>
<ul>
<li>NDA = Non-Disclosure Agreement, v cestine je to mlcenlivost, potazmo dohoda o mlcenlivosti, chcete-li.</li>
<li>Department = angl. preklad pro &quot;oddeleni&quot;</li>
<li>accesses = angl. preklad pro pristupy, v tomto kontextu prihlasovaci udaje do konkretniho systemu tak, aby byl zamestnanec schopen pracovat.</li>
<li>API = Application Programming Interface, laicky to lze popsat jako cast programu, ktera ma otevrenou &quot;zasuvku&quot; pro jine programy, ktere s timto programem muzou dale pracovat tak, jako by se jednalo o soucast.</li>
<li>PAN = Personal Area Network - Je to forma pripojeni k internetu (zjednoduseno) pres telefon, ale nejen nutne. Muzete i pracovat se soubory.</li>
<li>CI/CD = Continuous Integration, Continuous Deployment - jedna se o system hlavne pro vyvojare programu. Je to uceleny balik programu, ktere urychluji testovani, verzovani a v urcitych pripadech i automaticke &quot;zverejnovani&quot; novych verzi programu.</li>
<li>on-call = Dalo by se rici, ze se jedna o stav, kdy mate pracovni telefon v pohotovosti pro pripad, ze bude treba Vasich znalosti na reseni nejakeho pracovniho problemu. Zpravidla je to placene. Jste vlastne sluzebne porad v praci, jen ne fyzicky na pracovisti.</li>
</ul>
<h3>Jedna se o surove myslenky a vzpominky. Zalozeno na realnem zivote, ktery se neodehraval podle predstav. Autorem budiz clovek jinak uvazujici, prosim o zretel.</h3>
<p>Rekneme, ze to byla relativne bezna, vzhledem ke Gretine eco lobby zasnezena zima v prazske metropoli, akorat s jednim zasadnim rozdilem.<br />
Ano, pracoval jsem tam. Ve meste, o kterem jsem vzdy touzil, ze budu v nem pracovat, uzivat si kazdodenniho shonu cesty do prace v zacpach Praze vlastni. Parkrat se mi to i stalo.</p>
<p>Nebudu chodit kolem horke kase, ano, uz tam bohuzel nejsem.<br />
Nebo nastesti?</p>
<p><strong><em>Jak se to vezme.</em></strong></p>
<h2>Chapter one: The leaver</h2>
<p>Vse to vlastne zacalo v srpnu 2022. Mel jsem stabilne-nestabilni zamestnani v nenouzove-nouzovem stavu, jelikoz panovala pandemie a vlada si nutne potrebovala vydupat jinak nepotrebny nouzak, ktery vlastne priskrtil i to, co uz bylo davno priskrcene. Ale nechme politiku stranou a soustredme se na myslenky, ktere mi z toho zustaly.</p>
<p>Vazneji receno, nastala mi turbulence v zivote, kterou jsem musel resit a volba padla na hledani jineho, mnohem stabilnejsiho mista.<br />
Jelikoz v domovskem Brne moc prilezitosti nebylo a nekteri, me hodne blizci lide me &quot;nalomili&quot;, rozhodl jsem se jit do neznama, do Prahy. Volba padla na jednoho velmi znameho vyrobce 3Dtiskaren. Tusite, mozna, kdo to je.</p>
<p>Ano, Prusa Research, presneji jejich department Prusa Development, v podstate se jednalo o &quot;samostatnou&quot; spolecnost, ktera primo resila vyvoj.</p>
<p>Vse zacalo de facto v zari, odsouhlasili jsme si navzajem tzv. &quot;testovaci tyden&quot;, jelikoz jsem nevedel, co od te prace ocekavat. Tento tyden jsem skutecne do prace zde chodil a dostal zadani na vyreseni jedne chyby ve firmwaru  SL1S. Co to bylo konkretne rici nemohu, chci si zachovat uctu a v nekterych pripadech i NDA.</p>
<p>Tento tyden dopadl dobre, tuto chybu se mi povedlo najit, vysledovat jeji zdroj a tim tak chybu opravit. Tiskarna se tedy v teto chvili a pro tuto situaci chovala tak, jak bylo dle dokumentace a pozadavku treba.</p>
<h2>Chapter two: Good morning mr. Barter, looks like you're running late.</h2>
<p>Prvni den v nove praci zacal pomerne &quot;divoce&quot;. Vstaval jsem nekdy v 5 rano, v 6 cca autobus do Prahy a aby situace byla dokonala, na prijezdu jsme se zastavili v kolone, uz nekde od Chodova. A to se projevilo i na pozdnim prijezdu, kteremu zabranit neslo.<br />
Nicmene, vse dopadlo dobre, jelikoz jsem prisel cca 10 minut po zacatku.</p>
<p>Nicmene oproti ostatnim jsem uz zdejsi prostredi znal. Bylo mi receno, ze dalsi nove prichozi byli zrovna na prohlidce, kterou jsem absolvoval uz na testovacim tydnu a bylo mi tedy odpusteno.</p>
<p>Vse probihalo v poradku, po veskerych nalezitostech nutnych pro prvni den v praci  jsem se znovu shledal s mym primym vedoucim, mimo jine velmi prijemnym panem (mysleno vazne). Pomohl mi odnest veci na me zname pracoviste a ja tak mohl vlastne z fleku zacit pracovat.</p>
<p>Cekalo me me &quot;misto&quot;, ktere jsem si vyhledl uz pri testovacim tydnu. Zaujal jsem jej a se znalostmi z minula jsem si zridil velmi rychle ruzne pristupy, accesses a &quot;ozivil&quot; si  ucet na jejich internim komunikatoru.</p>
<blockquote>
<p><strong>I was ready to work.</strong></p>
</blockquote>
<p>Uterni prvni listopad se zacal chylit ke konci a pomalu jsem zacal resit presun na nove, lokalni bydleni.</p>
<p><strong>Na okraji Prahy.</strong></p>
<h2>Chapter three: The hacker</h2>
<p>Prvni den byl hekticky i v tom smyslu, ze jsem vlastne nemel zajistene ubytovani. Bylo to v jednom byte na okraji Prahy. Prestup na Kacerove z metra na 189 a skoro na konecnou. Radeji si ponecham, kde presne.<br />
Setkal jsem se majitelem, podepsal jsem smlouvu, zabydlel se a chtel si odpocinou.</p>
<p>A zjistil, ze tam vlastne neni internet.</p>
<p>Takto, ne ze bych na nem nejak zivotne zavisel a uprimne znam par lidi, kteri bez internetu nemohou zit, nicmene mi spousta programatoru da za pravdu, ze bez fungujiciho internetu se programuje hodne tezko, zvlaste, pisete-li robota pro ruzne protokoly predavajici zpravy. Je jedno, zda je to email, ci neco podobneho chatu na Facebooku ci Twitteru.</p>
<p><strong>Nebylo tam nic.</strong></p>
<p>Az na jednu restauraci.</p>
<p>Zacal jsem tedy premyslet, jak si alespon castecne zasituji sve bydleni, jelikoz jednoduchou metodou pokus-omyl jsem uhadl relativne trivialni heslo do te restaurace a dovolil si tak pujcit internet. Termin &quot;pujcit&quot; rikam zde zamerne, jelikoz po strance rychlosti jsem se dostal na hodnoty nizsi, nez bylo kdysi davno vytaceny pripojeni.</p>
<p>A ja jako dite jeste pro jistotu odpojoval kabel z pocitace, co kdyby nahodou byl internet pripojenej.</p>
<p>Nicmene, casem se mi povedlo kombinaci androidich telefonu, celkem kvalitniho USB kabelu z Aliexpressu zasitovat pocitac a ja tak mohl pokracovat v soukrome praci. JavaScript byl ku podivu tolerantni k rychlosti a ja tak mohl otestovat moduly do robota, ktery uz ani robotem nebyl, ale mel blize k ucelenemu reseni, chcete-li API.</p>
<p>Nicmene, nekteri lide, hlavne ze socialnich siti, mi nabidli SIM karty s internetem. Moc si cenim, ze mi to nabizeli, ale jakozto clovek snazici se o maximalni samostatnost jsem chtel nejdrive vycerpat veskere moznosti, ktere jsem mel.</p>
<p>Dovezl jsem si tedy z Brna stary router. V podstate to byl TPLink WRT741ND, na kterem bylo naflashovane openWRT. Takze, jak to maji admini radi, SSH a /etc/config/network, potazmo /etc/config/dhcp.</p>
<p><strong>To se neukazalo jako funkcni reseni.</strong></p>
<p>Jako druhe reseni se mi osvedcil kdysi davno pribuzneho Samsung s &quot;petkovym&quot; androidem. Pres soukromy notebook jsem si hral trochu s pripojenim pres PAN a dostal to do funkcniho stavu.</p>
<p>A takhle jsem zacal fungovat v podsate do konce ledna. Nicmene, pendloval jsem mezi &quot;Praglem&quot; a &quot;Schallingrattem&quot; kazde pondeli a kazdy ctvrtek.</p>
<p>V pondeli ve 4 rano,na budika a v 5 RegioJetem v Lowcostu do Prahy s misty nekvalitnim spankem, ve ctvrtek zpet domu, ale o pul 4.</p>
<p>A ano, tu SL1S jsem si zapujcil domu. Jako vybaveni nutne pro vyvoj firmwaru.</p>
<p>Casem jsem to dostal i do stavu, kdy jsem si od jedne pani v domovskem Brne koupil pojizdny kufr, lehce ho opravil a dostal tak moznost vozit 3Dtiskarny s sebou, v kufru.</p>
<h2>Chapter five: Nearby</h2>
<p>V podstate jsem jsem v lednu travil cas i hledanim jineho bydleni. To predchozi bylo pro me velmi neoptimalni, hlavne kvuli internetu. V podstate jsem veskere prace delal na koleni a misty si musel popojit k obchodu u zastavky, kde jsem vystupoval z autobusu linky 189 a chytat tam wifi.</p>
<p><strong>Ale take kvuli tomu dobrovolne zustaval v praci, nekdy i 13 hodin denne.</strong></p>
<p>Udelal jsem neco navic pro sebe po zkusenostech a znalostech, ale i se snazil dohnat to, co jsem treba zapomnel, ci se mohl posunout vice dopredu oproti puvodnim planum.</p>
<p><strong>Nicmene, zadarilo se.</strong></p>
<p>Nasel jsem si jiny podnajem a sel do nej. A posunul se do pohodlnejsi casti.<br />
Unor. Brezen.</p>
<p>Nic zasadnejsiho se nestalo, co se tyce prace. Kazdodenni shon, ale autobus a metro jsem vymenil za salinu. Nebo pardon - tramvaj. Mohl jsem si vybrat, zda rano sednu na &quot;socku&quot; (jak tomu nekdy prazsti rikaji - je to vubec pravda, nebo je to urban story?), nebo sednu na tramvaj. Oboji me doveze do prace, jen u metra jsem musel prestupovat na Florenci, coz mi davalo jakysi pocit komplexnosti cesty do prace nebo &quot;domu&quot;.</p>
<p>Nicmene, uz jsem se dostaval do pohodlne sfery sveho ziti, kdy jsem mohl (konecne) udelat relativne tradicni vylety do Makra, udelat si nakup a vratit se zpatky na byt zrelaxovat po praci.</p>
<p>At uz modelovanim, ci programovanim.<br />
ale take to dopadlo i tak, ze jsem prisel, dal si sprchu a sel spat. Jen zridkakdy jsem se dostal k modelovani, potazmo vyvoji, nicmene nasel se jeden vikend, kdy jsem tomu skutecne venoval cas.</p>
<h2>Chapter six: The Chaos</h2>
<p>Az cca do pocatku druheho tydne se nic zvlasniho nedelo, na druhou stranu ano, spousta veci byla neustale dynamicka. Letmo jsem se dotkl i veci v te dobe jeste v rannem pocatku vyvoje. Co se soukromeho casu tyce, uz jsem byl v relativni pohode a klidu.</p>
<p>Nicmene i tak jsem se snazil mimo pracovni dobu promptne resit pripominky a sledoval jsem ze sve vlastni vule interni CI/CD, jak probiha testovani a automatizace, ktera byla de facto moji denni naplni.</p>
<p>Zkratka, byl jsem on-call. Po ruce, ale v omezene mire a snazil se i tak dohnat veci, ktere treba usly, popripade chtely nejaky drobnejsi zasah programatora-devopsaka.</p>
<p><strong>To spatne ale teprve melo prijit.</strong></p>
<p>Zacal jsem si vsimat drobnych nedostatku v konunikaci. Jelikoz byl bohuzel odejit uz v lednu nas predchozi vedouci - ten, ktery me nabiral - komunikace se smrskla z formalni peti, misty ctyr lidi, na ctyri, respektive na tri.</p>
<p>Bohuzel i ja zacal zde &quot;selhavat&quot;, co se tyce komunikace. Neopochopeni zadani, spousta dotazovani, snaha pracovat samostatne a misty i drobne poznatky, jak vlastne ti lide fungovali v ramci tymu.</p>
<p>Z nekolika drobnych praci bokem pro jine tymy jsem se seznamil s dalsimi a par mych napadu na zlepseni se bohuzel minulo ucinkem.<br />
V zasade jsem se na zdrojovy kod podival, poznal jsem, ze je misty neoptimalni a navrhl zlepseni, jak to resit spravne, jak to mit dle konvenci.</p>
<p>Programatori z povolani me nejspise budou chapat, v kratkosti.<br />
V zasade jde o to, jak spravne automatizovat instalaci.</p>
<p>Treba Python to ma troska specificke, nicmene oproti JavaScriptu / NodeJS to neni zas tak daleko, v podstate slo o &quot;izolaci&quot; veci pro danou aplikaci od systemu, na coz si pamatuji z predchozich zamestnani - kde se mi to stalo - klient si spatne nastavil prostredi a v te chvili rozbil cely system. Program na instalaci jinych programu prestal z minuty na minutu fungovat a &quot;administratore, res to. Hlavne klientovi nerozbij to, co mu tam bezi.&quot;</p>
<h2>Chapter seven: The detail</h2>
<p>Zacal jsem hodne &quot;bojovat&quot; s nadrizenym. Nikoliv fyzicky, ale jak ma dane zadani vypadat, co tam ma byt. Takze, podivam-li se na to svym analytickym pohledem okorenenym o muj autismus (ano, mel jsem na nej papir, sebrali mi jej, pry jsem sobestacnej...), v podstate jsem komunikoval s clovekem, ktery mel siroke uvazovani, zatimco ja velmi detailni.</p>
<p>Treba rozchodit automatizovane SSH, protoze se sitarum par veci nelibilo a podle praxe by jste jako administratori nemeli mit volne dostupny server se superuzivatelem. <strong>Neexistuje.</strong></p>
<p>Zadani treba znelo &quot;Zajistit automaticke predavani klicu&quot;, coz jsem vyhotovil, ale treba tam chybel nejaky detail, ktery explicitne nebyl zminen.</p>
<p>Takze ano, zadani jsem formalne splnil, ale melo by to byt resene takto, takto, onakto... To proste v dokumentaci k zadani chybelo, takze i parkrat jsem se musel dotazovat, jak tedy ma vypadat vysledek.</p>
<p><strong>A to tez vzalo spoustu casu.</strong></p>
<p>Jelikoz tento clovek byl v &quot;officu&quot; (prakticky to spis byla dilna s pocitaci a hromadou elektroniky kolem) jen dvakrat tydne, komunikace docela vazla. Z predchozich zkusenosti z tymu dvou lidi - ja a nadrizeny - jsem se snazil udelat co nejvice prace, ale take nedelat ukvapene kroky.</p>
<p><strong>Mozna tusite tu kontradikci. Ano rovna se ne. A naopak.</strong></p>
<p><code>#define True False</code></p>
<p>A vysvetlovani zacalo.</p>
<p>Parkrat jsem uz byl &quot;na koberecku&quot;, snazice se vysvetlit sve uvazovani, jak resit tu praci a cim zlepsit svuj vlastni vykon.</p>
<h2>Chapter eight: Evacuation</h2>
<p>Nekdy v polovine dubna doslo k nejhorsimu, a sice meeting s HR, jak se veci budou odvijet dale. Bylo mi receno, ze jina moznost, nez dohoda uz neexistuje.</p>
<p>Takze ano, chteli se me zbavit. Podobny, ne-li stejny zpusob, jako v minule firme.<br />
Zadny vytykaci dopis, zadna snaha o to, jak zlepsit praci. Zadna snaha o to, jak bych tem druhym mohl rozumet lepe a jak pochopit kontext jejich myslenek, coz je kolikrat procesorove narocnejsi operace.</p>
<p>A take zadna reference k tomu dobrovolnemu prescasu, za leden budiz 40 hodin.</p>
<p>V podstate jeden cely tyden prescasu, ktery mi vlastne nikdo nezaplatil. Formalne ani nemusel. Ale jako snahu to akceptovat mohl.</p>
<p>Shrnul-li veskere udalosti, v zasade jsem s tim uz souhlasil. Vedel jsem, ze dojizdet kazde pondelni rano je dlouhodobe neudrzitelne, nehlede na absenci spanku, ktera byla mym vernym pritelem.</p>
<blockquote>
<p><strong>Ale nebyl to jedinny duvod</strong>.</p>
</blockquote>
<p>Zde se naskladalo nekolikero faktoru. Nevim, zda je vhodne o tom hovoriti, ale z vnitrniho prostredi firmy jsem se dozvedel, ze ne, ze je to spis fanouskovske zamestnani.</p>
<p>Na druhou stranu, ano, z jednoho platu jsem vlastne &quot;tahnul&quot; dve bydleni.<br />
Svuj domov 207,7 kilometru ode me a sve prechodne bydleni 5,3 kilometru ode me.</p>
<p>Nicmene doslo k nepchopeni na obou stranach. Oni chteli profesionala, dle me z fleku rozumejiciho dane problematice, zatimco ja jim mohl nabidnout jen pokrocile zkusenosti, byt se schopnosti se zorientovat, popripade si obstarat informace. Uplny zacatecnik jsem v te dobe nebyl ani zdaleka, vedel jsem o vyvoji softwaru, vedel jsem i o automatizaci vyvoje.</p>
<p>Koneckoncu automatizaci testovani firmwaru jsem vcetne podrobne dokumentace realizoval na zaklade tehdy existujicich poznamek z jinych tymu.</p>
<p>Byla to jedna z veci, co me opravdu bavila, nejenze jsem se dostal pomerne hluboko k samotnemu firmwaru, nicmene  naucil jsem firemni nastroje primo interagovat s tiskarnou, ktera se vlastne odzkousela sama a tim se prace nutna na rucni testovani mohla investovat jinde. To je pointa automatizace.</p>
<p>Nicmene lehce po polovine tydne jsem uz byl nucen opustit Prahu a vratit se zpet.</p>
<h2>Chapter nine: The retrospective</h2>
<p>I pres tyto spatnosti doted vzpominam na tuto praci jako jednu z mala, ktera me opravdu bavila. I do te miry, ze jsem byl ochoten investovat nemalou cast sveho soukromeho casu do reseni problemu, jak vyresit  automatizaci testovani firmwaru.</p>
<p>V podstate jsem delal DevOps praci, jen doplnenou o vyvoj, ktery treba nebyl tak zajimavy, nicmene byl nedilnou soucasti toho, co se tam delo.</p>
<p>Nicmene, chci to hodnotit i tak pozitivne, byt se hodne velke skraloupy a vymoly na silnici najdou.</p>
<ul>
<li>Co me hodne mrzi, je jakasi neochota poznat ten cas, co tam clovek investoval dobrovolne. Je to hodne subjektivni pocit a ano, bude to nahnute tak, ze ne kazdy s tim bude souhlasit.<br />
Tech 40 hodin mi asi uz nikdo nevrati, natozpak nezaplati, na druhou stranu cast toho kodu moji rukou napsanou tam nejspis je doted (ledaze se to dotycny clovek rozhodl cele vyhodit).</li>
<li>Osobni pocit z pracovne-uzkeho kolektivu spatny. Bohuzel nebyl jsem jedinny. Konkretni ale byt radeji nechci, opet, chci si zachovat uctu.</li>
<li>Vladne zde &quot;chaos&quot;. Termin &quot;chaos&quot; zminuji zamerne v uvozovkach, protoze ne kazdemu sedne dynamika prostredi, ackoliv me to misty nevadilo.</li>
<li>Chybela mi exaktnost a detailnost. Ale opet, subjektivni pocit. Predstavte si to tak, ze tatinek programator rekne synovi, aby mu popsal, jak si namazat nutellu na rohlik. Date mi za pravdu, ze kdyz syn rekne &quot;vezmi pomazanku&quot; tatinkovi a ten mu na to odpovi &quot;stala se chyba&quot;, asi tusite. Logicky, nemuze vzit pomazanku, kdyz je ta sklenice s nutellou uzavrena vikem. Musite udelat spousty kroku.<br />
A to zde chybelo. Co konkretne.</li>
<li>Teamleader failure: Nevim, zda je to muj osobni pocit, ale vlastne doted mi nikdo odtamtud neposlal referenci. Dokonce si ode me nadrizeny vyzadal kontakt na zaslani. Bud zapomnel, anebo se na to vykaslal. Vzhledem k 26. 12. - to druhe.<br />
Bez ohledu na to, ze na to treba ma obecne clovek pravo, nechal jsem zde hovorit realnou vuli pravnicke osoby.</li>
<li>Pomerne nedavno se mi dostal do rukou odkaz na YouTube od jednoho pomerne znameho recenzenta. Dozvedel jsem se spousty neprijemnych veci. Na zaklade tohoto si kladu otazku &quot;Chtel bych tam jeste pracovat? Proc to udelali takto? Proc se s tou spolecnosti nedohodli treba na spolupraci? Opravdu jim to za to stalo?&quot; Nechal jsem tam spoustu sveho casu a i kdyz tam treba nekoho konkretne nemusim, porad verim, ze jsou tam uzasni lide, kteri na to treba maji podobny pohled, jako ja. Nechci soudit.</li>
<li>Z partnerskeho hlediska a mimo profesni zkusenosti, troska jsem touzil, ze tam &quot;nejakou&quot; najdu. Na druhou stranu, asi je to tak dobre, protoze pri pomysleni, ze by ona chtela sedet na gauci se mnou a ja programovat... ona by trpela. Nedejboze, ona by chtela jit treba do virivky a ja chtel tisknout treba nahradni dil do domacnosti.</li>
</ul>
<p><strong>Ted ty pozitiva.</strong></p>
<ul>
<li>Dojizdeni do Prahy z Brna a domu do Brna bylo casove narocne. Nicmene davalo mi to jakysi pocit, ze nejenze byl o moji praci a snahu zajem, ale kdyz si to tak vezmu, brnak mel kapacitu na to nabidnout sve znalosti mimo svoji domovinu. Davalo mi to pocit, ze je o me zajem alespon z pracovniho hlediska a byt je to sebemrskacstvi, to dojizdeni me vlastne i bavilo. Prekonaval jsem dalky, prekonaval jsem sve limity a tak si vlastne dokazal, ze i s poruchou autistickeho spektra - nachylnemu k nestabilite - dobre fungovat i v chaotickem prostredi.</li>
<li>V podstate znam dalsi system na spravu verzi, coz je dobra zkusenost bez ohledu na ukonceni. Prohloubilo to znalosti a rozumim vnitrnimu fungovani. Dat si ted dohromady Kubernetes a orchestraci kontejnerizace ma ted pro me vetsi smysl, jak ten system vypada, jak ho nastavit... Toto na chodniku nenajdete.</li>
<li>Ano, poznal jsem tam spousty prijemnych lidi. Vyjma psychologicke nekompatibility - osobne - s konkretnim clovekem, nehodlam zde generalizovat pouze na zaklade negativniho vjemu. Ti lide to treba maji radi, radi tam pracuji bez ohledu na podminky, protoze je to bavi. 3Dtisk je vlastne zivotni styl, ne ze si tam nekde nekdo neco vytiskne, ale davate ostatnim moznost realizovat jejich sny.</li>
<li>Praha je mesto, jako kazde jine. Ma sve problemy, ma sva pozitiva. I pres tu misty stisnenost ti lide tady jen prozivaji stejny zivot, jako treba v Brne. Ac je to treba chaoticke, chci jen jako autista dokazat, ze i v takovem &quot;chaosu&quot; lze fungovat dobre a netreba se bat.</li>
<li>Vlastne jsem tam prinesl dobre napady a nektere z nich se zalibily. Na testovacim tydnu jsem se podival hloubeji do nekolika zdrojovych kodu a navrhl opravy. A ty uz tam zustaly.</li>
<li>Neni to jen prace s firmwarem, ale i bokem. Ac jsem z jazyka C na vysoke skole vyletel s F-kem, zkusenosti zustaly a muj kod v C v tom arduinu je doted soucasti tech testu, i kdyby byl neaktivni. V historii je a to ja pocitam.</li>
</ul>
<h2>Chapter ten: The assesment</h2>
<p>Hodnoceni sice uz probehlo a formalne je vice nedostatku, nez pozitiv. Nicmene jedna se o osobni pohled jednoho cloveka, ktery jeste k tomu mel pomerne &quot;davno&quot; papir, na kterym bylo napsany, ze mam o pulkolecka min, nebo vic. Zalezi.</p>
<p><strong>Nicmene jedna drobnost se zapomnela.</strong></p>
<p>Mimo praci, po konci smeny jsem treba jednou sedel i v breznu v kanclu a daval tam dohromady rozbite tiskarny. Kazdy by si rekl, ze odpad patri do odpadu, ale i pres to logo jsem se snazil ty stroje proste zprovoznit.</p>
<p>Jako 3Dtiskar nejen po strance uzivani, ale take i stavby, poskytovani rad a predevsim udrzby stroje v provozuschopne kondici jsem se nemohl jen tak divat na to, jak tam ty Mini lezely smutne v koute a jen cekaly, az je nekdo chnapne a slahne s nimi do odpadaku.<br />
A to i pres to, ze jsem uz tehdy mel problem s odrenymi rucemi a nechybelo mi daleko k tomu je mit vydrene az do krve po ruznych buzirkach a neplanovanych zrychlenich sroubovaku spatnym smerem.</p>
<p>Takze, v podstate jsem opravil i par tiskaren, ktere by jinak nekde skoncily a dal jim druhy zivot. Mozna tam ted nekde spokojene tisknou, protoze prakticky schopne jsou.</p>
<p>Na druhou stranu v popisu prace jsem mel napsano &quot;vyvoj a udrzba firmwaru&quot;.</p>
<p><strong>Pro SLA tiskarny.</strong></p>
<p>Ac to bylo vzdaleno tomu, co jsem delat chtel, dalo mi to i jakousi zpetnou vazbu, ze me nejvice bavi prace technika a programatora. V podstate umim &quot;vsechno&quot;. Navrhnout si nejaky stroj, vyvinout dilce, vytisknout je, pripravit pro tiskarnu nejen firmware, ale i veci okolo - v podstate postavit si vlastni linku pro vyvojare.</p>
<p>Pridam-li k tomu znalosti cloveka pracujiciho jako pocitacovy spravce a sitovy udrzbar, v podstate jsem schopen postavit podobny system na zelene louce. Co mi k tomu potreba je jen pocitac, internet a tabulka bily cokolady s lentilkami z teska.</p>
<p>Trochu premyslim i tak, ze kdyby mi dnes nekdo z jejich HR zavolal &quot;Dobry den, prehodnotili jsme nase rozhodnuti, chceme Te zpet&quot;, popremyslel bych o tom.</p>
<p>Zohlednim-li vsak sve zkusenosti z predchozich textu a tez i recenzi jejich produktu, zacinam vahat.</p>
<p><strong>Je mi to lito, protoze i pres ideologicky nesouhlas to byla prvni prace v zivote, u ktere me bavilo i prescasovat a delat veci navic.</strong><br />
Ano, nejsem dokonaly a mam spoustu vyrobnich zavad, nicmene dnes mi spousta lidi predava slova &quot;Mohli mit jednoho z nejvetsich fanousku do 3Dtisku, ktery tomu opravdu rozumi&quot;.</p>
<p>Navrhnout si 3Dtiskarnu, postavit ji a udrzovat ji neni prace na tyden, ale z vlastni zkusenosti na rok. Dal jsem do ni 10 tisic a dodneska stale funguje.</p>
<p><strong>Takze zaverem, mohli mit skutecneho fanouska, zel, uz ho nemaji. Mrzi me to, protoze Prusa Research a Development jsou jinak fajn firmy s fajn lidmi. Ty lidi to take bavi a i tam se najdou myslenkove podobni memu uvazovani.</strong></p>
<p><strong>A toto myslim vazne.</strong></p>

<div class="twitter-share"><a href="https://twitter.com/intent/tweet?url=https%3A%2F%2Fwww.hardwired.dev%2F2023%2F12%2F26%2Fthe-calamity%2F&#038;via=hessevalentino" class="twitter-share-button">Tweet</a></div><p>The post <a href="https://www.hardwired.dev/2023/12/26/the-calamity/">The Calamity</a> first appeared on <a href="https://www.hardwired.dev">Hard Wired</a>.</p>]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Puppeteer download BOT</title>
		<link>https://www.hardwired.dev/2022/10/31/puppeteer-download-bot/</link>
		
		<dc:creator><![CDATA[John Doe]]></dc:creator>
		<pubDate>Mon, 31 Oct 2022 13:35:28 +0000</pubDate>
				<category><![CDATA[Docker]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Různé]]></category>
		<category><![CDATA[bot]]></category>
		<category><![CDATA[chrome]]></category>
		<category><![CDATA[docker]]></category>
		<category><![CDATA[headless]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[nodejs]]></category>
		<category><![CDATA[puppeteer]]></category>
		<category><![CDATA[scraping]]></category>
		<category><![CDATA[web]]></category>
		<category><![CDATA[web-scraping]]></category>
		<guid isPermaLink="false">http://wordpress.hardwired.dev/?p=774</guid>

					<description><![CDATA[<p>O co jde Uděláme bota co načte webovou stránku, klikne na čudlík a stáhne soubor. Použijeme k tomu knihovnu Puppeteer &#62;&#62;&#62;</p>
<p>The post <a href="https://www.hardwired.dev/2022/10/31/puppeteer-download-bot/">Puppeteer download BOT</a> first appeared on <a href="https://www.hardwired.dev">Hard Wired</a>.</p>]]></description>
										<content:encoded><![CDATA[<div id="bsf_rt_marker"></div><h1>O co jde</h1>
<p>Uděláme bota co načte webovou stránku, klikne na čudlík a stáhne soubor.</p>
<p>Použijeme k tomu knihovnu <a href="https://pptr.dev/" title="Puppeteer">Puppeteer</a> a samotný kód budeme pouštět v <a href="https://www.docker.com/" title="Dockeru">Dockeru</a>.</p>
<blockquote>
<p>Větší podrobnosti a vysvětlení zakládání NodeJs projektu v Dockeru najde v článku <a href="http://wordpress.hardwired.dev/nodejs-develompent-v-dockeru/" title="NodeJS develompent v Dockeru">NodeJS develompent v Dockeru</a>.</p>
</blockquote>
<h1>Příprava projektu</h1>
<p>Založíme nový projekt:</p>
<pre><code class="language-shell">mkdir puppet
cd puppet
npm init -y</code></pre>
<p>Upravíme <code>package.json</code> a přidáme do něj knihovnu <code>puppeteer</code>:</p>
<pre><code class="language-json">{
  &quot;name&quot;: &quot;puppet&quot;,
  &quot;version&quot;: &quot;1.0.0&quot;,
  &quot;description&quot;: &quot;&quot;,
  &quot;main&quot;: &quot;index.js&quot;,
  &quot;scripts&quot;: {
    &quot;start&quot;: &quot;node index.js&quot;
  },
  &quot;keywords&quot;: [],
  &quot;author&quot;: &quot;&quot;,
  &quot;license&quot;: &quot;ISC&quot;,
  &quot;dependencies&quot;: {
    &quot;puppeteer&quot;: &quot;^19.2.0&quot;
  }
}</code></pre>
<p>Vytvoříme <code>Dockerfile</code>, který použije jako základ obraz s <code>node v16</code>, nainstaluje <code>Chrome prohlížeč</code> a nakopíruje projekt do Docker obrazu.</p>
<pre><code class="language-shell">FROM node:16

RUN apt-get update &amp;&amp; apt-get install gnupg wget -y &amp;&amp; \
  wget --quiet --output-document=- https://dl-ssl.google.com/linux/linux_signing_key.pub | gpg --dearmor &gt; /etc/apt/trusted.gpg.d/google-archive.gpg &amp;&amp; \
  sh -c &#039;echo &quot;deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main&quot; &gt;&gt; /etc/apt/sources.list.d/google.list&#039; &amp;&amp; \
  apt-get update &amp;&amp; \
  apt-get install google-chrome-stable -y --no-install-recommends &amp;&amp; \
  rm -rf /var/lib/apt/lists/*

ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true \
    PUPPETEER_EXECUTABLE_PATH=/usr/bin/google-chrome-stable

WORKDIR /app
COPY package*.json .
RUN npm install
COPY . ./</code></pre>
<p>Vytvoříme <code>index.js</code> soubor a necháme ho jen vypsat zprávu do konzole.</p>
<pre><code class="language-shell">touch index.js</code></pre>
<pre><code class="language-javascript">console.log(&#039;Hello from docker&#039;)</code></pre>
<p>Není úplně špatné vytvořit i <code>.dockerignore</code> soubor.</p>
<pre><code class="language-shell">node_modules
Dockerfile
.dockerignore
.git
.gitignore
README.md
docker-compose*</code></pre>
<p>Sestavíme obraz.</p>
<pre><code class="language-shell">docker build -t puppet-app-image .</code></pre>
<p>A spustíme Docker kontejner.</p>
<pre><code class="language-bash"># %cd% je aktuální složka ve Windows, pro jiné systémy použijte adekvátní náhradu

docker run -d --tty --name puppet-app -v %cd%:/app -v /app/node_modules puppet-app-image</code></pre>
<blockquote>
<p>--tty parametr je nutný. V opačném případě se Docker kontejner spustí a pak hned úspěšně ukončí. <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Za normálních okolností předpokládá, že v něm něco poběží a až se to ukončí tak skončí taky. TTY toto chování potlačí.</p>
</blockquote>
<p>Jakmile kontejner běží, můžeme se do něj přihlásit:</p>
<pre><code class="language-shell">docker exec -it puppet-app bash</code></pre>
<p>Vevnitř se ocitneme ve složce <code>/app</code>, kde je náš projekt a můžeme zkusit spustit náš program.</p>
<pre><code class="language-shell">nodejs index.js</code></pre>
<p>Měl by nám odpovědět <code>Hello from docker</code>.</p>
<h1>Bot</h1>
<p>Pro ukázku bude bot stahovat zdrojový kód puppeteeru z githubu. Upravíme <code>index.js</code> následovně.</p>
<pre><code class="language-javascript">const puppeteer = require(&#039;puppeteer&#039;)

;(async () =&gt; {
    const browser = await puppeteer.launch({
        headless: true,
        args: [&#039;--no-sandbox&#039;],
    })

    const page = await browser.newPage()
    page.setViewport({ width: 1920, height: 1080 })

    const client = await page.target().createCDPSession()
    await client.send(&quot;Page.setDownloadBehavior&quot;, {
        behavior: &quot;allow&quot;,
        downloadPath: &#039;./&#039;
    })

    await page.goto(
        &#039;https://github.com/puppeteer/puppeteer/releases/tag/puppeteer-core-v19.2.0&#039;,
        { waitUntil: &#039;networkidle2&#039; }
    )
    await page.waitForTimeout(1000)

    await page.click(&#039;#repo-content-turbo-frame div.mb-3 &gt; details &gt; div &gt; div &gt; ul &gt; li:nth-child(1) &gt; div.d-flex.flex-justify-start.col-12.col-lg-9 &gt; a&#039;)
    await page.waitForTimeout(5000)

    await page.screenshot({ path: &#039;./screen.jpg&#039;, fullPage: true })

    await browser.close()
})()</code></pre>
<p>Naimportujeme do našeho projektu knihovnu <code>puppeteer</code>.</p>
<pre><code class="language-javascript">const puppeteer = require(&#039;puppeteer&#039;)</code></pre>
<p>Budeme volat asynchronní funkce v java scriptu a budeme používat klíčové slovo <code>await</code>, které čeká na provedení asynchronní funkce. Problém je to, že <code>await</code> se může objevit jen v asynchronní funkci. Tudíž náš kód musíme do jedné takové zabalit a rovnou spustit.</p>
<pre><code class="language-javascript">;(async () =&gt; {
    // code
})()</code></pre>
<p>Vytvoříme nový <code>headless prohlížeč</code>.</p>
<pre><code class="language-javascript">const browser = await puppeteer.launch({
    headless: true,
    args: [&#039;--no-sandbox&#039;],
})</code></pre>
<p>Vytvoříme novou <code>stránku/tab</code> a nastavíme rozlišení.</p>
<pre><code class="language-javascript">const page = await browser.newPage()
page.setViewport({ width: 1920, height: 1080 })</code></pre>
<p>Pro tuto konkrétní stránku nastavíme automatické stahovaní do určitého adresáře. V našem případě adresář s projektem. Takhle nebudeme vyvolávat dialog pro umístění stahovaného souboru.</p>
<pre><code class="language-javascript">const client = await page.target().createCDPSession()
await client.send(&quot;Page.setDownloadBehavior&quot;, {
    behavior: &quot;allow&quot;,
    downloadPath: &#039;./&#039;
})</code></pre>
<p>V naší <code>stránce/tabu</code> otevřeme požadovanou github stránku.</p>
<pre><code class="language-javascript">await page.goto(
    &#039;https://github.com/puppeteer/puppeteer/releases/tag/puppeteer-core-v19.2.0&#039;,
    { waitUntil: &#039;networkidle2&#039; }
)
await page.waitForTimeout(1000)</code></pre>
<p>Klikneme na odkaz pro stažení a chvíli počkáme, než se soubor stáhne <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
<pre><code class="language-javascript">await page.click(&#039;#repo-content-turbo-frame div.mb-3 &gt; details &gt; div &gt; div &gt; ul &gt; li:nth-child(1) &gt; div.d-flex.flex-justify-start.col-12.col-lg-9 &gt; a&#039;)
await page.waitForTimeout(5000)</code></pre>
<p>K definování toho na co se má kliknout se používá <a href="https://www.w3schools.com/CSSREF/css_selectors.php" title="CSS Selector">CSS Selector</a> (<a href="https://drafts.csswg.org/selectors/" title="draft">draft</a>, <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors" title="mdn">mdn</a>). Ten pomocí html elementů, tříd, atributů a dalších dokáže sestavit unikátní cestu k prvku na stránce. Stránky generované nějakým frameworkem umí potrápit i s takhle dlouhým selektorem, jako v tomto případě.</p>
<p><img decoding="async" src="http://wordpress.hardwired.dev/wp-content/uploads/2022/10/githubsource.jpg" alt="" /></p>
<p>Pak už si jen uděláme momentku, v jakém stavu stránku opouštíme.</p>
<pre><code class="language-javascript">await page.screenshot({ path: &#039;./screen.jpg&#039;, fullPage: true })</code></pre>
<p>A prohlížeč korektně zavřeme.</p>
<pre><code class="language-javascript">await browser.close()</code></pre>
<h1>Spuštění kódu</h1>
<p>V konzoli se připojíme k našemu kontejneru.</p>
<pre><code class="language-bash">docker exec -it puppet-app bash</code></pre>
<p>A spustíme našeho bota.</p>
<pre><code class="language-bash">node index.js</code></pre>
<p>Pokud vše proběhne, jak má, tak ve složce projektu budete mít jak stažený soubor, tak fotku stránky těsně před tím než jste ji opustili.</p>
<p><img decoding="async" src="http://wordpress.hardwired.dev/wp-content/uploads/2022/10/puppeteer_screen.jpg" alt="" /></p>
<p>Toto je velice hrubý nástřel toho, co Puppeteer dokáže na konkrétním případě. Výhodou je, že se opravdu spustí prohlížeč, ve kterém můžeme ovládat i dynamicky generované <code>single page</code> aplikace. Nevýhodou je, že pokud se struktura stránky změní moc, tak musíte upravit i váš kód.</p>
<p>Happy coding!</p>

<div class="twitter-share"><a href="https://twitter.com/intent/tweet?url=https%3A%2F%2Fwww.hardwired.dev%2F2022%2F10%2F31%2Fpuppeteer-download-bot%2F&#038;via=hessevalentino" class="twitter-share-button">Tweet</a></div><p>The post <a href="https://www.hardwired.dev/2022/10/31/puppeteer-download-bot/">Puppeteer download BOT</a> first appeared on <a href="https://www.hardwired.dev">Hard Wired</a>.</p>]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>NodeJS develompent v Dockeru</title>
		<link>https://www.hardwired.dev/2022/09/17/nodejs-develompent-v-dockeru/</link>
		
		<dc:creator><![CDATA[John Doe]]></dc:creator>
		<pubDate>Sat, 17 Sep 2022 12:39:52 +0000</pubDate>
				<category><![CDATA[Docker]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Různé]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[docker]]></category>
		<category><![CDATA[docker-compose]]></category>
		<category><![CDATA[expressjs]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[nodejs]]></category>
		<category><![CDATA[nvm]]></category>
		<category><![CDATA[vagrant]]></category>
		<category><![CDATA[vscode]]></category>
		<guid isPermaLink="false">https://hessevalentino.cz/?p=378</guid>

					<description><![CDATA[<p>Pokud se motáte okolo webového vývoje (frontendy, api a pod...) a používáte JavaScript (respektive NodeJS), tak jste se určitě už &#62;&#62;&#62;</p>
<p>The post <a href="https://www.hardwired.dev/2022/09/17/nodejs-develompent-v-dockeru/">NodeJS develompent v Dockeru</a> first appeared on <a href="https://www.hardwired.dev">Hard Wired</a>.</p>]]></description>
										<content:encoded><![CDATA[<div id="bsf_rt_marker"></div><p>Pokud se motáte okolo webového vývoje (frontendy, api a pod...) a používáte <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript">JavaScript</a> (respektive <a href="https://nodejs.org/en/">NodeJS</a>), tak jste se určitě už setkali s následujícím problémem. Různé projekty jsou napsány pod různými verzemi programovacího jazyka a ne vždy je možné vše upgradovat na poslední verzi. </p>
<p><span id="more-378"></span></p>
<ul>
<li>Můžete používat knihovny, které ještě nejsou upraveny pro novou verzi.</li>
<li>Starší verze frameworku s poslední verzí jazyka nefunguje.</li>
<li>Zpětná nekompatibilita.</li>
<li>Prostě nejsou peníze nebo není čas zabývat se přechodem a přepisem aplikace na poslední verzi.</li>
</ul>
<p>Důvodů může být milión, ale klíčové je to, že pokud jste to vy co musí do těchto  projektů zasahovat, tak musíte provozovat více verzí jazyka.</p>
<p>Pokud se potýkáte s tímto problémem, tak nehledě na jakém operačním systému se nacházíte, budou scénáře podobné.</p>
<h2>Scénář 1 - Jedna verze v systému</h2>
<p>Tohle je pro popisovaný problém asi nejhorší situace. Máte v systému jednu verzi jazyka. Všechny projekty, na kterých pracujete, musejí běžet pod touhle verzí. Zpravidla to skončí tak, že verze jazyka bude taková, jakou potřebuje ten nejstarší (legacy) projekt. Může vás to zablokovat na tolik, že nebudete moci použít poslední verze frameworků nebo poslední funkcionalitu, protože nebudou tak starou verzi jazyka podporovat.</p>
<h2>Scénář 2 - NVM</h2>
<p><a href="https://github.com/nvm-sh/nvm">Node Version Manager</a> (NVM) je utilita, která vám umožní provozovat více verzí jazyka na jednom stroji a přepínat mezi nimi. Existuje jak pro Linux, MacOs, tak i pro Windows. Ve chvíli kdy se přepínáte mezi verzemi a používáte současně jednu, je to přímočaré a elegantní řešení. Ve chvíli, kdy potřebujete mít několik projektů puštěných naráz, pod různými verzemi jazyka, už samozřejmě vyžaduje určitou míru konfigurace. Ale zrovna k tomuto scénáři nemám moc co říct, protože jsem provozoval jen tu nejprimitivnější formu čistě přepínání mezi verzemi. Každopádně se jedná o funkční řešení.</p>
<h2>Scénář 3 - Vagrant</h2>
<p><a href="https://www.vagrantup.com/">Vagrant od HashiCorp</a> používá pro oddělení prostředí virtualizaci. Vytvoříte předpis, který nakonfiguruje virtuální stroj, ve kterém následně aplikaci vyvíjíte. Je možné nakonfigurovat celý ekosystém, aplikace, databáze, cache atd.  Teoreticky je to geniální věc. Nehledě na systém máte předpis, který spustíte na jakémkoliv systému a vytvoří vám stejné prostředí pro vývoj. V praxi to už tak veselé nebylo. Je pravda, že jsem Vagrant použil naposledy před několika lety. Problémy byly zpravidla nějaká specifika operačních systému, zvláště Windows. Nebo situace co se musely řešit &quot;hackem&quot;, protože ještě neexistovalo nativní řešení a samozřejmě hromada virtuálních mašin, když bylo prostředí pro vývoj rozsáhle. I tak jsem na tom byl nějakou dobu schopný vyvíjet a šlo to docela dobře. Čas pokročil a určitě byla hromada věcí dotažena. Určitě se jedná o funkční řešení.</p>
<h2>Scénář 4 - Docker</h2>
<p>Jak už název článku napovídá, budeme řešit <a href="https://www.docker.com/">Docker</a>. Docker používá kontejnery. Kontejner je softwarová jednotka, která zapouzdřuje kód i s jeho závislostmi. Na rozdíl od standardní virtualizace, nerozebíhá znovu celý operační systém, ale používá operační systém hostitele. Nejlíp to asi vysvětlí přímo citace ze stránek Dockeru.</p>
<blockquote>
<p>A container is a standard unit of software that packages up code and  all its dependencies so the application runs quickly and reliably from  one computing environment to another. A Docker container image is a  lightweight, standalone, executable package of software that includes  everything needed to run an application: code, runtime, system tools,  system libraries and settings.</p>
<p>Container images become containers at runtime and in the case of Docker containers – images become containers when they run on <a href="https://www.docker.com/products/container-runtime">Docker Engine</a>. Available for both Linux and Windows-based applications, containerized  software will always run the same, regardless of the infrastructure.  Containers isolate software from its environment and ensure that it  works uniformly despite differences for instance between development and staging.</p>
<p>from <a href="https://www.docker.com/resources/what-container/">https://www.docker.com/resources/what-container/</a></p>
</blockquote>
<p>V praxi to znamená, že máte v kontejneru souborový systém operačního systému dle libosti. Doinstalujete si potřebné balíčky pro běh vašeho projektu a tento kontejner můžete izolovaně pouštět tam, kde jsou kontejnery podporované. Speciálně Docker funguje pod Linuxem, MacOs i Windows.</p>
<pre><code>+------------++-----------+
|    APP1    ||   APP2    |
+------------++-----------+
+------------++-----------+
|  Bin/Libs  ||  Bin/Libs |
+------------++-----------+
+-------------------------+
|         Docker          |
+-------------------------+
+-------------------------+
|    Operační systém      |
+-------------------------+
+-------------------------+
|         Server          |
+-------------------------+</code></pre>
<p>&quot;Back in my days&quot;, když jsem si chtěl na serveru rozjet nějaké služby, buď jsem provozoval nějakou virtualizaci nebo jsem to všechno naplácal do jednoho operačního systému. Jedno ze zásadních úskalí bylo to, že různé služby potřebovaly různé balíky, verze knihoven a míru konfigurace. Pokud člověk nebyl dostatečně obezřetný mohl si &quot;roze***t&quot; celý systém a vše poslat do kytek. V lepším případě byla mašina v jakémsi meta ezo stavu, kdy něco jelo a něco ne.</p>
<p>S Dockerem hromada problémů opadla. Každá služba je izolovaný kontejner, který si své závislosti bere sebou. Pokud něco nefunguje, vadný kontejner se vymaže, ale vše ostatní jede dál. Drtivé množství běžných služeb (wiki, databáze, ...) mají už dnes nachystané a nakonfigurované obrazy. V uvozovkách je stačí jen spustit. Jako všechno si to sebou nese i negativa. Neaktualizované knihovny v kontejneru jsou bezpečnostní riziko. Nebo pokud si nevytváříte kontejner sami tak musíte důvěřovat autorovi, že tam nenasadil nějakou breberku. Ale vždy je něco za něco.</p>
<p>Jak už asi tušíte, z tohoto stručného popisu, použití pro výše popsaný problém bude jasné. Vytvoří se pro projekt Docker kontejner a tak budou všechny závislosti projektu izolovány od hlavního operačního systému. Takhle můžete mít pohodlně puštěné aplikace pod různou verzí NodeJS na jednom stroji. Je to v podstatě jako Vagrant, <a href="https://www.virtualbox.org/">VirtualBox</a> nebo obecně virtualizace. Akorát teda ne tak úplně. <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
<p>Nešpinit systém, na kterém vyvíjíte, závislostmi projektu je podle mě dlouhodobě udržitelná cesta.</p>
<p>Plus mají kontejnery dnes ještě jednu výhodu. <a href="https://aws.amazon.com/getting-started/hands-on/deploy-docker-containers/">Cloudové služby</a> vám zpravidla umožňují posílat kontejnery i do produkce.</p>
<h2>Čestná zmínka</h2>
<p>Výše uvedené scénáře nejsou určitě jediné, ale jsou to ty, se kterými jsem se setkal osobně.</p>
<p>Minimálně ještě existuje možnost vyvíjet na vzdáleném operačním systému přes <a href="https://cs.wikipedia.org/wiki/Secure_Shell">SSH</a>. <a href="https://code.visualstudio.com/">Visual Studio Code</a> tento <a href="https://code.visualstudio.com/docs/remote/ssh">vzdálený vývoj</a> umožňuje. Jako taky možnost, ale za mě teda trochu exotická. Ale když není zbytí, lepší než drátem do oka.</p>
<h2>NodeJS projekt v Dockeru</h2>
<blockquote>
<p>Toto není kompletní návod pro člověka, který se v životě neotřel o Docker nebo o NodeJS a vývoj API. Do takových podrobností článek nejde. Zabývá se jak rozjet projekt v Dockeru a předpokládá už určité znalosti. Pardon. <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
</blockquote>
<p>V první řadě budeme potřebovat <a href="http://wordpress.hardwired.dev/instalace-dockeru/">nainstalovat Docker</a>. Případně na desktopu (a hlavně na Windows) to bude <a href="https://docs.docker.com/desktop/">Docker Desktop</a>.</p>
<p>Pokusíme se rozjet vývoj <a href="https://zdrojak.cz/clanky/rest-architektura-pro-webove-api/">REST API</a> s použitím <a href="https://expressjs.com/">ExpressJs</a>.</p>
<p>Pro náš projekt budeme mít následující strukturu.</p>
<pre><code class="language-bash">nodejs-docker-workflow \
    .dockerignore
    .env
    Dockerfile
    index.js
    package.json
    package-lock.json</code></pre>
<p><code>pakcage.json</code> obsahuje konfiguraci projektu.</p>
<pre><code class="language-json">{
  &quot;name&quot;: &quot;nodejs-docker-workflow&quot;,
  &quot;version&quot;: &quot;1.0.0&quot;,
  &quot;description&quot;: &quot;&quot;,
  &quot;main&quot;: &quot;index.js&quot;,
  &quot;scripts&quot;: {
    &quot;start&quot;: &quot;node index.js&quot;,
    &quot;dev&quot;: &quot;nodemon -L index.js&quot;
  },
  &quot;keywords&quot;: [],
  &quot;author&quot;: &quot;&quot;,
  &quot;license&quot;: &quot;ISC&quot;,
  &quot;dependencies&quot;: {
    &quot;express&quot;: &quot;^4.18.1&quot;
  },
  &quot;devDependencies&quot;: {
    &quot;nodemon&quot;: &quot;^2.0.20&quot;
  }
}</code></pre>
<p>V části závislostí budeme pro náš jednoduchý projekt potřebovat pouze balíček <a href="https://www.npmjs.com/package/express">express</a>. V rámci vývojových závislostí (devDependencies) budeme používat <a href="https://www.npmjs.com/package/nodemon">nodemon</a>. Ten nám umožní restart serveru, pokud se vyskytne změna v hlídaném adresáři.</p>
<p><code>index.js</code> obsahuje kód našeho REST API.</p>
<pre><code class="language-javascript">const express = require(&#039;express&#039;)

const app = express()

app.get(&#039;/&#039;, (req, res) =&gt; {
    res.send({
        data: {
            message: &#039;Hello world!&#039;,
            exclamation: &#039;!!!&#039;,
        },
    })
})

const port = process.env.PORT || 3000

app.listen(port, () =&gt; console.log(`listening on port ${port}`))</code></pre>
<p>Primitivní API vracející &quot;Hello world!&quot;.</p>
<p><code>Dockerfile</code> obsahuje sestavení našeho obrazu kontejneru.</p>
<pre><code class="language-dockerfile">FROM node:16
WORKDIR /app
COPY package*.json .
RUN npm install
COPY . ./
ENV PORT 3000
EXPOSE $PORT
CMD [&quot;npm&quot;, &quot;run&quot;, &quot;dev&quot;]</code></pre>
<p><code>FROM node:16</code> říká, že použijeme základní image, na kterém je už nachystán NodeJS verze 16.</p>
<p><code>WORKDIR /app</code> nás v rámci kontextu přesune do složky <code>/app</code>.</p>
<p><code>COPY package*.json</code> . překopíruje do obrazu do <code>/app</code> soubor <code>package.json</code>.</p>
<p><code>RUN npm install</code> spustí instalaci závislostí na základe <code>package.json</code>.</p>
<p><code>COPY . ./</code> překopíruje soubory z aktuálního adresáře do obrazu do <code>/app</code>.</p>
<p><code>ENV PORT 3000</code> vytvoří proměnou prostředí.</p>
<p><code>CMD [&quot;npm&quot;, &quot;run&quot;, &quot;dev&quot;]</code> spustí skript definovaný v <code>package.json</code>, který spustí nodemon.</p>
<p><code>.dockerignore</code> obsahuje seznam souboru a složek co se nebudou kopírovat do obrazu.</p>
<pre><code class="language-bash">node_modules
Dockerfile
.dockerignore
.git
.gitignore
README.md
docker-compose*</code></pre>
<p><code>.env</code> je seznam proměnných prostředí, které chceme aplikovat na kontejner.</p>
<pre><code>PORT=4000</code></pre>
<p>Základní projekt máme nachystaný. A sestavíme na základě <code>Dockerfile</code> obraz pro náš kontejner.</p>
<pre><code class="language-bash">docker build -t node-app-image .</code></pre>
<p>Následně pak můžeme překontrolovat, že obraz skutečně existuje.</p>
<pre><code class="language-bash">docker image ls</code></pre>
<p>Obraz je nachystaný a můžeme spustit samotný kontejner.</p>
<pre><code class="language-bash"># WINDOWS %cd%
# POWERSHELL ${pwd}
# MAC, LINUX $(pwd)

# --env PORT=4000
# --env-file ./.env

docker run -p 3000:4000 -d --name node-app --env-file ./.env -v %cd%:/app -v /app/node_modules node-app-image</code></pre>
<p><code>-p 3000:4000</code> přesměruje port 3000 z hostitelského systému na port 4000 Docker kontejneru.</p>
<p><code>-d</code> spustí Docker kontejner na pozadí.</p>
<p><code>--name node-app</code> pojmenuje kontejner.</p>
<p><code>--env-file ./.env</code> nastaví proměnné systému na základě souboru <code>.env</code>.</p>
<p><code>-v %cd%:/app</code> zajistí zrcadlení aktuálního adresáře a jeho změny do <code>/app</code> v kontejneru.</p>
<p><code>-v /app/node_modules</code> vytvoří volume pro node moduly. Díky tomu se nestane to, že přes zrcadlený adresář pošleme příkaz k jejich smazání v kontejneru. Je to trochu &quot;ohák&quot;, ale funční.</p>
<p><code>node-app-image</code> je název obrazu na základě kterého vytváříme kontejner.</p>
<p>Pokud nedostaneme nějaké chybové hlášení, můžeme zkontrolovat, že vše jede.</p>
<p>Můžeme se podívat na aktuálně běžící kontejnery.</p>
<pre><code class="language-bash">docker ps</code></pre>
<p>A můžeme také zkontrolovat logy pro konkrétní kontejner.</p>
<pre><code class="language-bash">docker logs node-app</code></pre>
<p>Když do prohlížeče zadáme <code>localhost:3000</code> dostaneme následující.</p>
<pre><code class="language-json">{&quot;data&quot;:{&quot;message&quot;:&quot;Hello world!&quot;,&quot;exclamation&quot;:&quot;!!!&quot;}}</code></pre>
<p>Pokud v souboru <code>index.js</code> upravíme odpověď serveru, <code>nodemon</code> na to zareaguje a restartuje API s aktuální změnou.</p>
<p>Jestliže se potřebujeme &quot;přihlásit&quot; dovnitř kontejneru do příkazové řádky, použijeme <code>docker exec</code>.</p>
<pre><code class="language-bash">docker exec -it node-app bash</code></pre>
<p>V této chvíli máme plně funkční NodeJS projekt v Dockeru. Pokud přidáme nebo odebereme balíčky, musím znovu sestavit obraz pomocí <code>docker build -t node-app-image .</code> a Docker kontejner spustit.</p>
<p>Předtím je teda nutné kontejner zabít, to uděláme pomocí <code>docker rm</code>.</p>
<pre><code class="language-bash">docker rm node-app -fv</code></pre>
<p><code>-fv</code> odstraní i běžící kontejner (nemusíme zastavovat) a na něj navázané anonymní volumes (svazky).</p>
<p>Tohle je taková &quot;základní&quot; verze. Spouštění Docker kontejneru, s veškerou konfigurací v příkazové řádce může být po čase otrava. Jednodušším řešením je použití <a href="https://docs.docker.com/compose/gettingstarted/">Docker-Compose</a>.</p>
<p>V našem projektu vytvoříme soubor <code>docker-compose.yml</code>.</p>
<pre><code class="language-yaml">version: &quot;3&quot;
services:
  node-app:
    container_name: node-app
    build: .
    ports:
      - &quot;3000:4000&quot;
    volumes:
      - ./:/app
      - /app/node_modules
    env_file:
      - ./.env
#    environment:
#      - PORT=4000 </code></pre>
<p><code>version: &quot;3&quot;</code> je <a href="https://docs.docker.com/compose/compose-file/compose-versioning/">verze zápisu Docker Compose</a> souboru.</p>
<p><code>node-app:</code> uvozuje sekci našeho kontejneru.</p>
<p><code>container_name: node-app</code> pojmenuje náš kontejner. Pokud ho nepojmenujeme sami, Docker to udělá za nás.</p>
<p><code>build: .</code> sestaví obraz pomocí <code>Dockerfile</code>.</p>
<p><code>ports:</code> přesměrování portů.</p>
<p><code>volumes:</code> seznam volumes.</p>
<p><code>env_file:</code> nastavuje proměnné prostředí.</p>
<p>Docker Compose soubor jen kopíruje to, co jsme nastavovali pro <code>docker run</code>. Ale takhle nám zůstane nastavení pěkně a strukturovaně uloženo.</p>
<p>Předpis spustíme pomocí příkazu <code>docker-compose</code>.</p>
<pre><code class="language-bash">docker-compose up -d</code></pre>
<p>Pokud přidáme parametr <code>--build</code>, tak se při každém spuštění znovu sestaví obraz.</p>
<pre><code class="language-bash">docker-compose up -d --build</code></pre>
<p>Pomocí <code>docker-compose</code> provádíme i smazání.</p>
<pre><code class="language-bash">docker-compose down -v</code></pre>
<p><code>-v</code> jako v předchozím případě smaže i připojené anonymní volumes.</p>
<p>Tohle je už o něco lepší verze, ale nepočítá s tím, že bychom chtěli různá prostředí. Například <code>development</code> a <code>production</code>. Budeme muset upravit <code>Dockerfile</code>, <code>docker-compose.yml</code> a přidat <code>docker-compose.dev.yml</code> a <code>docker-compose.prod.yml</code>.</p>
<p>Do <code>Dockerfile</code> přidáme podmínku pro různá prostředí.</p>
<pre><code class="language-dockerfile">FROM node:16
WORKDIR /app
COPY package*.json .

ARG NODE_ENV
RUN if [ &quot;$NODE_ENV&quot; = &quot;development&quot; ]; \
        then npm install; \
        else npm install --only=production; \
        fi

COPY . ./
ENV PORT 3000
EXPOSE $PORT
CMD [&quot;node&quot;, &quot;index.js&quot;]</code></pre>
<p><code>ARG NODE_ENV</code> definujeme použití argumentu <code>NODE_ENV</code>.</p>
<p><code>RUN if [ &quot;$NODE_ENV&quot; = &quot;development&quot; ]; \</code> na základě aktuální typu prostředí provedeme klasický <code>npm install</code> nebo produkční.</p>
<p><code>CMD [&quot;node&quot;, &quot;index.js&quot;]</code> je příkaz do produkčního prostředí, protože nespouštíme <code>nodemon</code>. Každopádně ho stejně budeme definovat znovu v Docker Compose souborech.</p>
<p><code>docker-compose.yml</code> trošku zeštíhlíme a necháme v něm jen společná nastavení pro všechna prostředí.</p>
<pre><code class="language-yaml">version: &quot;3&quot;
services:
  node-app:
    container_name: node-app
    build: .
    ports:
      - &quot;3000:4000&quot;
    environment:
      - PORT=4000  </code></pre>
<p><code>docker-compose.dev.yml</code> nastavím pro naše <code>development</code> prostředí.</p>
<pre><code class="language-yaml">version: &quot;3&quot;
services:
  node-app:
    build:
      context: . 
      args:
        NODE_ENV: development
    volumes:
      - ./:/app
      - /app/node_modules
    environment:
      - NODE_ENV=development  
    command: npm run dev</code></pre>
<p>Všimněte si, že jsme rozšířili definici <code>build</code> a přidali argument <code>NODE_ENV</code>, který se používá v <code>Dockerfile</code>. Nastavení <code>volumes</code> je stejné jako předtím a přepsali jsme <code>CMD</code> v <code>Dockerfile</code> na náš <code>development</code> příkaz.</p>
<p><code>docker-compose.prod.yml</code> bude jednodušší, protože pro produkci nepotřebujeme zrcadlit adresáře.</p>
<pre><code class="language-yaml">version: &quot;3&quot;
services:
  node-app:
    build:
      context: . 
      args:
        NODE_ENV: production
    environment:
      - NODE_ENV=production
    command: node index.js</code></pre>
<p>Principiálně je to to samé co <code>docker-compose.dev.yml</code>.</p>
<p>Pokud budeme chtít spustit <code>development</code> verzi, zavoláme.</p>
<pre><code class="language-bash">docker-compose -f docker-compose.yml -f docker-compose.dev.yml up -d</code></pre>
<p>Popřípadě, pokud chceme spustit i vytváření obrazu.</p>
<pre><code class="language-bash">docker-compose -f docker-compose.yml -f docker-compose.dev.yml up -d --build</code></pre>
<p>Odstranění kontejneru provedeme promocí.</p>
<pre><code class="language-shell">docker-compose -f docker-compose.yml -f docker-compose.dev.yml down -v</code></pre>
<p>Pro produkční build to bude analogické.</p>
<pre><code class="language-bash">docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d --build
docker-compose -f docker-compose.yml -f docker-compose.prod.yml down -v</code></pre>
<p>TADÁ a to je vše přátele. Aplikace funguje pořád stejně, ale už můžeme rozlišovat mezi <code>development</code> a <code>production</code> prostředtím.</p>
<hr />
<p><em>ad1)</em> Článek popisuje pouze absolutní základ, pravá síla Dockeru se projeví ve chvíli, kdy si nakonfigurujete kompletní ekosystém a budete ho schopni jednoduše replikovat.</p>
<p>ad2) Článek ukazuje situaci, kdy nebudete mít na svém stroji nainstalován NodeJS a nepustíte <code>npm install</code> na svém stroji. Tím si nevygenerujete <code>package-lock.json</code>. To může být problém při generování produkčních kontejnerů. <code>package-lock.json</code> obsahuje deterministický popis závislostí. Do produkce chcete jít s takovým stromem závislostí, který už máte odzkoušený. Pro doplnění citace z <a href="https://docs.npmjs.com/cli/v8/configuring-npm/package-lock-json">docs.npm.com</a>.</p>
<blockquote>
<p><code>package-lock.json</code> is automatically generated for any operations where npm modifies either the <code>node_modules</code> tree, or <code>package.json</code>. It describes the exact tree that was generated, such that subsequent installs are able to generate identical trees, regardless of intermediate dependency updates.</p>
<p>Describe a single representation of a dependency tree such that teammates, deployments, and continuous integration are guaranteed to install exactly the same dependencies.</p>
<p>from <a href="https://docs.npmjs.com/cli/v8/configuring-npm/package-lock-json">https://docs.npmjs.com/cli/v8/configuring-npm/package-lock-json</a></p>
</blockquote>
<p>Proto je vhodnější postup na hostitelské systému používat <code>npm i</code> pro instalaci nových balíčku do projektu. Tím se bude generovat i <code>package-lock.json</code>. Toto nijak neomezuje používání rozličných verzí NodeJS v kontejnerech.</p>
<p>ad3) Docker se chová tak, že spustí příkaz a když doběhne, tak se vypne. V případě, že rozjíždíte NodeJs API, tak je to jedno. Tam se předpokládá, že pouštíte nějaký <code>nodemon</code> nebo něco co udrží API v běhu. Pokud ale chcete vyvíjet něco co neběží ve smyčce a z <code>Dockerfile</code> odeberete <code>CMD příkaz</code>, tak se <code>Docker container</code> spustí a úspěšně ukončí. Jde tím předejít přidáním parametru <code>tty</code>.<br />
Ten zajistí, že se kontejner hned neukončí.</p>
<p>Pro <code>docker-compose</code>:</p>
<pre><code class="language-yaml">mydocker:
    tty: true</code></pre>
<p>Pro <code>docker run</code>:</p>
<pre><code class="language-bash">docker run -d --tty ......</code></pre>

<div class="twitter-share"><a href="https://twitter.com/intent/tweet?url=https%3A%2F%2Fwww.hardwired.dev%2F2022%2F09%2F17%2Fnodejs-develompent-v-dockeru%2F&#038;via=hessevalentino" class="twitter-share-button">Tweet</a></div><p>The post <a href="https://www.hardwired.dev/2022/09/17/nodejs-develompent-v-dockeru/">NodeJS develompent v Dockeru</a> first appeared on <a href="https://www.hardwired.dev">Hard Wired</a>.</p>]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Self hosted Matrix server</title>
		<link>https://www.hardwired.dev/2022/09/15/self-hosted-matrix-server/</link>
		
		<dc:creator><![CDATA[John Doe]]></dc:creator>
		<pubDate>Thu, 15 Sep 2022 15:19:19 +0000</pubDate>
				<category><![CDATA[Docker]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Raspberry]]></category>
		<category><![CDATA[docker]]></category>
		<category><![CDATA[element]]></category>
		<category><![CDATA[end-to-end]]></category>
		<category><![CDATA[fediverse]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[matrix]]></category>
		<category><![CDATA[portainer]]></category>
		<category><![CDATA[postgre]]></category>
		<category><![CDATA[privacy]]></category>
		<category><![CDATA[raspberry]]></category>
		<category><![CDATA[rpi]]></category>
		<category><![CDATA[synapse]]></category>
		<guid isPermaLink="false">https://hessevalentino.cz/?p=297</guid>

					<description><![CDATA[<p>Těžko by jste asi hledali někoho, kdo nikdy neposlal ani jednu zprávu přes Messenger nebo podobnou službu. Asi můžeme říct, &#62;&#62;&#62;</p>
<p>The post <a href="https://www.hardwired.dev/2022/09/15/self-hosted-matrix-server/">Self hosted Matrix server</a> first appeared on <a href="https://www.hardwired.dev">Hard Wired</a>.</p>]]></description>
										<content:encoded><![CDATA[<div id="bsf_rt_marker"></div><p>Těžko by jste asi hledali někoho, kdo nikdy neposlal ani jednu zprávu přes Messenger nebo podobnou službu. Asi můžeme říct, že je to jeden z nejrozšířenějších komunikačních prostředků současnosti.</p>
<p>S rostoucím podílem těchto služeb v oblasti všeobecné komunikace vyvstal i takový nešvar. Hovorově bychom mohli říct &quot;fízlování&quot;. V reálu to bude nějaká sada algoritmů, která se snaží na základě klíčových slov, frází nebo nějaké sofistikovanější analýzy rozpoznat závadný či protiprávní obsah. Tyto praktiky se většinou zaštiťují ochranou dětí před XYZ a podobné zavádějící důvody. Ale o problematice svobody slova a práva na soukromí tento příspěvek není.</p>
<p>Klasické textové komunikační služby ukládají vaše zprávy v nešifrované podobě. Nemáte vůbec tušení jak dlouho se vaše data uchovávají a za jakým účelem (většinou marketing) mohou být přeprodávána. A už vůbec nevíte, kdy a kdo, to může použít proti vám. (byť třeba vytržené z kontextu)</p>
<p>Situaci si můžete vylepšit tím, že používáte &quot;end-to-end&quot; šifrované komunikátory. Telegram, Signal, Threema a podobně. Při této metodě komunikace by v ideálním případě zprostředkovatel neměl být schopný zprávy jakkoliv dešifrovat.</p>
<p>Tak je to možná v ideálním světě. V tom našem můžeme narazit na pár úskalí. Musíme zprostředkovateli věřit, že dodává takovou službu jakou inzeruje. I když nemusí vidět přímo obsah zpráv, stále si může uchovávat kdo, kdy a s kým komunikoval. Nepříjemností taky je registrace podmíněná poskytnutím telefonního čísla. Telefonní číslo za určitých podmínek dává smysl a používání aplikace je díky němu komfortnější, ale taky je to další vektor útoku na vaši identitu.</p>
<p>Alternativní možností je zprovoznit vlastní Matrix server. Pokud o tom slyšíte poprvé, můžete prozkoumat <a href="https://fediverse.party/" title="Fediverse ekosystém">Fediverse ekosystém</a> a pořádně se ponořit do králičí nory.</p>
<p>Jen ve zkratce popis na wikipedii.</p>
<blockquote>
<p>The fediverse (a portmanteau of federation and universe) is an ensemble of federated (i.e. interconnected) servers that are used for web publishing (i.e. social networking, microblogging, blogging, or websites) and file hosting, but which, while independently hosted, can communicate with each other. On different servers (instances), users can create so-called identities. These identities are able to communicate over the boundaries of the instances because the software running on the servers supports one or more communication protocols which follow an open standard.[1] As an identity on the fediverse, users are able to post text and other media, or to follow posts by other identities.[2] In some cases, users can show or share data (video, audio, text, and other files) publicly or to a selected group of identities and allow other identities to edit other users\' data (such as a calendar or an address book). from <a href="https://en.wikipedia.org/wiki/Fediverse">https://en.wikipedia.org/wiki/Fediverse</a> </p>
</blockquote>
<p>Pro naše účely není tento aspekt úplně klíčový.</p>
<p>Co vlastně získáme tím, že zprovozníme vlastní Matrix server?</p>
<ul>
<li>Komunikace používá end-to-end šifrování. Nikdo kromě příjemce by neměl být schopný zprávu vidět.</li>
<li>Data leží na našem &quot;železe&quot; a v námi kontrolovaném operačním systému. Sami si můžete překontrolovat jak a jaká data jsou v databázi ukládána.</li>
<li>Starou dobrou registraci s uživatelským jménem a heslem. Nejsou potřeba žádné emaily nebo telefonní čísla.</li>
<li>Nikdo probíhající komunikaci &quot;nefízluje&quot;.</li>
<li>Kód je open source. Každý do něho může nahlédnout. Možnost úmyslného zanešení nějakého škodlivého kusu kódu je hodně malá. Komunita by jim to brzy omlátila o hlavu.</li>
<li>Máte na výběr z vícero klientů. I když tohle může být někdy i negativum než pozitivum.</li>
<li>Moderní klienti moc nezaostávají za předními hráči na trhu. Ano jde poznat, že do toho nebylo nasypáno tolik peněz a „user experience“ není tak „smooth“. To ale nic nemění na tom, že můžete posílat zprávy, fotky, videa, emoji, nálepky, gify nebo provádět video telefonáty. Všechno je technicky funkční.</li>
<li>Je možné provozovat komunikaci s jednotlivými lidmi, skupinové komunikace nebo vytvářet místnosti.</li>
</ul>
<p>Výhod se najde asi ještě více, ale tou nejdůležitější vlastní kontrola.</p>
<p>Nevýhod se najde taky dost. Vůbec samotné rozeběhnutí vyžaduje lehce technický „skill“. Plus věci okolo jako domény, reverzní proxy atd.</p>
<p>Tak a teď teda k tomu co a jak je potřeba rozeběhnout.</p>
<p>Rozeběhnout to můžete skoro na čemkoliv, ale já pro naše účely použil RPi 3B+ s SSD diskem. Pro běh jednotlivých služeb použijeme Docker a Docker-Compose. Jak nainstalovat Docker <a href="http://wordpress.hardwired.dev/instalace-dockeru/" title="je popsáno v jiném článku">je popsáno v jiném článku</a> na tomto blogu.</p>
<p>Náš stack obsahje následující Docker obrazy.</p>
<ul>
<li>portainer/portainer-ce:latest</li>
<li>matrixdotorg/synapse:latest</li>
<li>postgres:14</li>
<li>vectorim/element-web:latest</li>
</ul>
<p><a href="https://www.portainer.io/" title="Portainer">Portainer</a> slouží jen pro pohodlnější správu Docker kontejnerů.</p>
<p>Jako <a href="https://matrix.org/" title="Matrix">Matrix</a> server použijeme <a href="https://github.com/matrix-org/synapse" title="Synapse">Synapse</a>. Je to implementace Matrix serveru v Pythonu.</p>
<p>Postgres 14 bude naše databáze. V základu používá Synapse Sqlite3, ale pokud máme tu možnost, bude lepší použít Postgres.</p>
<p><a href="https://element.io/" title="Element">Element</a> je webový klient pro Matrix server.</p>
<p>V domovském adresáři si vytvoříme složku matrix-stack a začneme skládat Docker-Compose soubor.</p>
<pre><code class="language-shell">cd ~
mkdir matrix-stack
nano ./matix-stack/docker-compose.yml</code></pre>
<pre><code class="language-yaml">version: &#039;3.3&#039;

services:
  portainer:
    container_name: portainer
    image: portainer/portainer-ce:latest
    restart: always
    ports:
      - &quot;9000:9000&quot;
    volumes:
      - portainer_data:/data
      - /var/run/docker.sock:/var/run/docker.sock

  synapse:
    container_name: synapse
    image: matrixdotorg/synapse:latest
    restart: always
    ports:
      - 8008:8008
    volumes:
      - /var/docker_data/matrix:/data

  postgres:
    container_name: postgres
    image: postgres:14
    restart: unless-stopped
    ports:
      - &quot;5432:5432&quot;
    volumes:
     - /var/docker_data/postgresdata:/var/lib/postgresql/data

    environment:
     - POSTGRES_DB=synapse
     - POSTGRES_USER=synapse
     - POSTGRES_PASSWORD=SUPERSECRETLONGPASSWORD
     - POSTGRES_INITDB_ARGS=--lc-collate C --lc-ctype C --encoding UTF8

  element:
    container_name: element
    image: vectorim/element-web:latest
    restart: unless-stopped
    ports:
      - &quot;80:80&quot;
    volumes:
      - /var/docker_data/element-config.json:/app/config.json

volumes:
  portainer_data:</code></pre>
<p>Pro Synapse místo Sqlite3 použijeme Postgre databázi. Víceméně se standardním nastavením kromě jedné věci.</p>
<pre><code class="language-yaml">POSTGRES_INITDB_ARGS=--lc-collate C --lc-ctype C --encoding UTF8</code></pre>
<p>Matrix vyžaduje aby <strong>LC_COLLATE</strong> a <strong>LC_TYPE</strong> nastaveny na <strong>C</strong>. Má to co do činění s akceptováním různých znakových sad.</p>
<blockquote>
<p>When LC_CTYPE is C or POSIX, any character set is allowed, but for other settings of LC_CTYPE there is only one character set that will work correctly. Since the LC_CTYPE setting is frozen by initdb, the apparent flexibility to use different encodings in different databases of a cluster is more theoretical than real, except when you select C or POSIX locale (thus disabling any real locale awareness).</p>
</blockquote>
<p>Před tím, než pustíme <strong>docker-compose</strong>, je potřeba udělat ještě pár věcí.</p>
<p>Potřebujeme vygenerovat konfigurační soubor pro <strong>Synapse</strong> server.</p>
<pre><code class="language-bash">docker run -it --rm \
    -v &quot;/var/docker_data/matrix:/data&quot; \
    -e SYNAPSE_SERVER_NAME=matrix.YOUR_DOMAIN.com \
    -e SYNAPSE_REPORT_STATS=no \
    matrixdotorg/synapse:latest generate</code></pre>
<p>A v nově vygenerovaném souboru předělat Sqlite3 na Postgre. Stačí zakomentovat sekci s Sqlite3 a vložit novou.</p>
<pre><code class="language-yaml">database:
  name: psycopg2
  args:
    user: synapse
    password: SUPERSECRETLONGPASSWORD
    database: synapse
    host: postgres
    cp_min: 5
    cp_max: 10</code></pre>
<p>Potom je potřeba vytořit konfigurační soubor pro Element.</p>
<pre><code class="language-bash">sudo nano /etc/docker_data/element-config.yaml</code></pre>
<pre><code class="language-json">{
    &quot;default_server_config&quot;: {
        &quot;m.homeserver&quot;: {
            &quot;base_url&quot;: &quot;https://matrix.YOUR_DOMAIN.com&quot;,
            &quot;server_name&quot;: &quot;matrix.YOUR_DOMAIN.com&quot;
        },
        &quot;m.identity_server&quot;: {
            &quot;base_url&quot;: &quot;https://vector.im&quot;
        }
    },
    &quot;brand&quot;: &quot;Element&quot;,
    &quot;integrations_ui_url&quot;: &quot;https://scalar.vector.im/&quot;,
    &quot;integrations_rest_url&quot;: &quot;https://scalar.vector.im/api&quot;,
    &quot;integrations_widgets_urls&quot;: [
        &quot;https://scalar.vector.im/_matrix/integrations/v1&quot;,
        &quot;https://scalar.vector.im/api&quot;,
        &quot;https://scalar-staging.vector.im/_matrix/integrations/v1&quot;,
        &quot;https://scalar-staging.vector.im/api&quot;,
        &quot;https://scalar-staging.riot.im/scalar/api&quot;
    ],
    &quot;hosting_signup_link&quot;: &quot;https://element.io/matrix-services?utm_source=element-web&amp;utm_medium=web&quot;,
    &quot;bug_report_endpoint_url&quot;: &quot;https://element.io/bugreports/submit&quot;,
    &quot;uisi_autorageshake_app&quot;: &quot;element-auto-uisi&quot;,
    &quot;showLabsSettings&quot;: true,
    &quot;piwik&quot;: {
        &quot;url&quot;: &quot;https://piwik.riot.im/&quot;,
        &quot;siteId&quot;: 1,
        &quot;policyUrl&quot;: &quot;https://element.io/cookie-policy&quot;
    },
    &quot;roomDirectory&quot;: {
        &quot;servers&quot;: [
            &quot;matrix.org&quot;,
            &quot;gitter.im&quot;,
            &quot;libera.chat&quot;
        ]
    },
    &quot;enable_presence_by_hs_url&quot;: {
        &quot;https://matrix.org&quot;: false,
        &quot;https://matrix-client.matrix.org&quot;: false
    },
    &quot;terms_and_conditions_links&quot;: [
        {
            &quot;url&quot;: &quot;https://element.io/privacy&quot;,
            &quot;text&quot;: &quot;Privacy Policy&quot;
        },
        {
            &quot;url&quot;: &quot;https://element.io/cookie-policy&quot;,
            &quot;text&quot;: &quot;Cookie Policy&quot;
        }
    ],
    &quot;hostSignup&quot;: {
      &quot;brand&quot;: &quot;Element Home&quot;,
      &quot;cookiePolicyUrl&quot;: &quot;https://element.io/cookie-policy&quot;,
      &quot;domains&quot;: [
          &quot;matrix.org&quot;
      ],
      &quot;privacyPolicyUrl&quot;: &quot;https://element.io/privacy&quot;,
      &quot;termsOfServiceUrl&quot;: &quot;https://element.io/terms-of-service&quot;,
      &quot;url&quot;: &quot;https://ems.element.io/element-home/in-app-loader&quot;
    },
    &quot;sentry&quot;: {
        &quot;dsn&quot;: &quot;https://029a0eb289f942508ae0fb17935bd8c5@sentry.matrix.org/6&quot;,
        &quot;environment&quot;: &quot;develop&quot;
    },
    &quot;posthog&quot;: {
        &quot;projectApiKey&quot;: &quot;phc_Jzsm6DTm6V2705zeU5dcNvQDlonOR68XvX2sh1sEOHO&quot;,
        &quot;apiHost&quot;: &quot;https://posthog.element.io&quot;
    },
    &quot;features&quot;: {
        &quot;feature_spotlight&quot;: true
    },
    &quot;map_style_url&quot;: &quot;https://api.maptiler.com/maps/streets/style.json?key=fU3vlMsMn4Jb6dnEIFsx&quot;
}</code></pre>
<p>V horní části souboru upravte pro vaši doménu.</p>
<pre><code class="language-json">&quot;default_server_config&quot;: {
        &quot;m.homeserver&quot;: {
            &quot;base_url&quot;: &quot;https://matrix.YOUR_DOMAIN.com&quot;,
            &quot;server_name&quot;: &quot;matrix.YOUR_DOMAIN.com&quot;
        },
        &quot;m.identity_server&quot;: {
            &quot;base_url&quot;: &quot;https://vector.im&quot;
        }
    }</code></pre>
<p>Tak a teď už můžeme pustit ten docker. Přesuneme se do složky s Docker-Compose souborem a spustíme příkaz docker-compose.</p>
<pre><code class="language-bash">cd ~/matrix-stack
docker-compose up -d</code></pre>
<p>Pokud všechno proběhne dle plánu, tak se můžete zkusit přihlásit do Portaineru a měli byste vidět něco takového.</p>
<p><img decoding="async" src="http://wordpress.hardwired.dev/wp-content/uploads/2022/09/matrix-containers.jpg" alt="" /></p>
<p>Teď se potřebujeme připojit do docker kontejneru kde beží Synapse odkud budeme přes příkaz <code>register_new_matrix_user</code> přidávat uživatele.</p>
<pre><code class="language-bash">docker exec -it synapse /bin/bash</code></pre>
<pre><code class="language-bash">register_new_matrix_user -c /data/homeserver.yaml http://127.0.0.1:8008</code></pre>
<p>Příkaz vás následně navede co vyplnit.</p>
<p>V tomto bodě nám už vše běží a máme vytvořeného prvního uživatele. Pokud se přes prohlížeč podíváte na <code>http://&lt;ip-adresa-vaseho-stroje&gt;:8008</code> uvidíte že Matrix server běži.</p>
<p><img decoding="async" src="http://wordpress.hardwired.dev/wp-content/uploads/2022/09/matirx-is-running.jpg" alt="" /></p>
<p>Určitě se nechceme vždy připojovat na <code>http://&lt;ip-adresa-vaseho-stroje&gt;:8008</code>. To by bylo poněkud nepohodlné a pravděpodobně by to fungovalo jen v lokální síti. Ještě bychom mohli přesměrovat porty na router, ale to je prašť jako uhoď.</p>
<p>Lepší bude použít doménu jako <code>matrix.nasedomena.eu</code> a samozřejmě <code>https</code> protokol, aby naše data po internetu nelítala jen tak. </p>
<p>Bude to chtít zařídit několik věcí. </p>
<ul>
<li>Je potřeba mít veřejnou statickou IP.</li>
<li>Koupit nějakou doménu.</li>
<li>Vyřídit si certifikát. Například přes službu <a href="https://letsencrypt.org/" title="Let&#039;s Encrypt">Let's Encrypt</a>.</li>
<li>Zprovoznit reverzní proxy, která bude zpracovávat příchozí požadavky. Pro tento článek použijeme webový server <a href="https://www.nginx.com/" title="Nginx">Nginx</a> jako reverzní proxy. Jak zprovoznit Nginx jako reverzní proxy najdete v <a href="http://wordpress.hardwired.dev/nginx-jako-reverzni-proxy/" title="článku na tomto webu">článku na tomto webu</a>.</li>
</ul>
<p>Budeme chtít používat <code>https://matrix.nasedomena.eu</code> a <code>https://element.nasedomena.eu</code>.</p>
<p>Pro <code>element.nasedomena.eu</code> bude konfigurační soubor pro Nginx vypadat nějak takhle.</p>
<pre><code> server {
    listen 80;
    server_name element.nasedomena.eu;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;

    server_name element.nasedomena.eu;

    ssl on;
    ssl_certificate /etc/letsencrypt/live/nasedomena.eu/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/nasedomena.eu/privkey.pem; # managed by Certbot

    location / {
        proxy_pass http://192.168.1.111:80;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection &#039;upgrade&#039;;
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}</code></pre>
<p>Veškerý nešifrovaný provoz směrující na <code>element.nasedomena.eu</code> bude přesměrován na šifrovaný.</p>
<p>Pro samotný Matrix server je nutné do konfigurace přidat ještě pár věcí.</p>
<pre><code>server {
    listen 80;
    server_name matrix.nasedomena.eu;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    listen 8448 ssl http2 default_server;
    listen [::]:8448 ssl http2 default_server;

    server_name matrix.nasedomena.eu;

    ssl on;
    ssl_certificate /etc/letsencrypt/live/nasedomena.eu/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/nasedomena.eu/privkey.pem; # managed by Certbot

     location /.well-known/matrix/client {
                return 200 &#039;{&quot;m.server&quot;: {&quot;base_url&quot;: &quot;matrix.nasedomena.eu:443&quot;}}&#039;;
                default_type application/json;
                add_header Access-Control-Allow-Origin *;
        }

    location /.well-known/matrix/server {
                default_type application/json;
                add_header Access-Control-Allow-Origin *;
                return 200 &#039;{&quot;m.server&quot;:&quot;matrix.nasedomena.eu:443&quot;}&#039;;
        }

    location / {
        proxy_pass http://192.168.1.111:8008;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection &#039;upgrade&#039;;
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}</code></pre>
<p>Jestli máme všechno dobře nakonfigurováno, můžeme zkusit <code>https://element.nasedomena.eu</code>. Poběží tu webový klient pro Matrix. Budeme muset upravit domovský server na náš <code>matrix.nasedomena.eu</code>, protože v základu je tam nastavený <code>matrix.org</code>. Poté se můžeme přihlásit jako uživatel, kterého jsme vytvořili v jednom z předchozích kroků.</p>
<p><img decoding="async" src="http://wordpress.hardwired.dev/wp-content/uploads/2022/09/element-login.jpg" alt="" /></p>
<p>K připojení můžete samozřejmě využít jakéhokoliv klienta Matrixu. Přidejte další další uživatele pomocí kroků výše a můžete začít komunikovat naprosto soukromě. Komunikace s dalšími uživateli v rámci Fediverse je také možná. Samotný Synapse jde různě nakonfigurovat. Můžete například povolit registraci uživatelů přes klienty a další možnosti. Konfigurace Synapse ale není náplní tohoto článku.</p>

<div class="twitter-share"><a href="https://twitter.com/intent/tweet?url=https%3A%2F%2Fwww.hardwired.dev%2F2022%2F09%2F15%2Fself-hosted-matrix-server%2F&#038;via=hessevalentino" class="twitter-share-button">Tweet</a></div><p>The post <a href="https://www.hardwired.dev/2022/09/15/self-hosted-matrix-server/">Self hosted Matrix server</a> first appeared on <a href="https://www.hardwired.dev">Hard Wired</a>.</p>]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
