<?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>H. Peter Pfeufer</title>
	<atom:link href="https://ppfeufer.de/feed/" rel="self" type="application/rss+xml" />
	<link>https://ppfeufer.de</link>
	<description>Web developer and WordPress enthusiast</description>
	<lastBuildDate>Thu, 04 Apr 2024 18:31:48 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.0</generator>
	<item>
		<title>Gentoo Portage: Clean up Your Mess</title>
		<link>https://ppfeufer.de/gentoo-portage-clean-up-your-mess/</link>
					<comments>https://ppfeufer.de/gentoo-portage-clean-up-your-mess/#comments</comments>
		
		<dc:creator><![CDATA[H. Peter Pfeufer]]></dc:creator>
		<pubDate>Thu, 04 Apr 2024 18:31:47 +0000</pubDate>
				<category><![CDATA[Gentoo Linux]]></category>
		<category><![CDATA[Portage]]></category>
		<guid isPermaLink="false">https://ppfeufer.de/?p=31193</guid>

					<description><![CDATA[By default, Gentoo&#8217;s emerge downloads and saves a lot of distfiles. And by a lot I mean … A LOT!And they are not removed automatically when the emerge process has finished successfully. Over time this will accumulate quite a collection...]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">By default, Gentoo&#8217;s <code>emerge</code> downloads and saves a lot of distfiles. And by a lot I mean … A LOT!<br>And they are not removed automatically when the <code>emerge</code> process has finished successfully.</p>



<p class="wp-block-paragraph">Over time this will accumulate quite a collection of files in <code>/vat/cache/distfiles</code> that are no longer needed and just collecting dust there. Not to mention the space wasted by those files.</p>



<p class="wp-block-paragraph">Of course, you can remove these files manually occasionally, but wouldn&#8217;t it be nice if portage would take care of this?</p>



<p class="wp-block-paragraph">And portage can!<br>With a little tweak that I found quite some time ago.</p>



<p class="wp-block-paragraph">Save the following as <code>/etc/portage/bashrc</code>:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
# darkelf-features-0.1::darkelf
# created for ::darkelf overlay.
# by Simon the Sorcerer - http://homepages.uni-paderborn.de/neuron/gentoo/darkelf/
#
# This enables cleaning the distfiles after every emerge,
# to enable this feature set
# DARKELF_FEATURES=&quot;postmerge_distclean&quot;
# in /etc/portage/make.conf or per command basis e.g.:
# DARKELF_FEATURES=&quot;postmerge_distclean&quot; emerge ...

darkelf_postmerge_distclean() {
    echo cleaning distfiles for ${CATEGORY}/${PF} ...

    if &#x5B; -z $DISTDIR ] ; then
        echo ERROR: DISTDIR is empty!
        exit 1
    fi

    for f in $DISTDIR/* ; do
        echo deleting &quot;`readlink -f $f`&quot; ...
        rm -r &quot;`readlink -f $f`&quot;
    done
}

post_pkg_postinst() {
    if grep -q &quot;postmerge_distclean&quot; &lt;&lt;&lt; $DARKELF_FEATURES ; then
        darkelf_postmerge_distclean
    fi
}
</pre></div>


<p class="wp-block-paragraph">And now add the following to your <code>/etc/portage/make.conf</code> file:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
# Portage clean up
# Remove downloaded distfiles from ${DISTDIR}
# see /etc/portage/bashrc
DARKELF_FEATURES=&quot;postmerge_distclean&quot;
</pre></div>


<p class="wp-block-paragraph">From now on, <code>emerge</code> will remove the downloaded distfile for the package that just got merged successfully from <code>/var/cache/distfiles</code> and clean up after itself this way. All you have to do is to clean out that directory one last time.</p>



<p class="wp-block-paragraph">One thing though, please don&#8217;t change the code, it&#8217;s not mine. So keep the copyright/creator header in the bash script.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://ppfeufer.de/gentoo-portage-clean-up-your-mess/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>Raspberry Pi &#8211; Change SWAP Size</title>
		<link>https://ppfeufer.de/raspberry-pi-change-swap-size/</link>
					<comments>https://ppfeufer.de/raspberry-pi-change-swap-size/#comments</comments>
		
		<dc:creator><![CDATA[H. Peter Pfeufer]]></dc:creator>
		<pubDate>Mon, 20 Mar 2023 10:01:36 +0000</pubDate>
				<category><![CDATA[Raspberry Pi]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Memory]]></category>
		<category><![CDATA[Raspberry PI]]></category>
		<category><![CDATA[SWAP]]></category>
		<guid isPermaLink="false">https://ppfeufer.de/?p=31128</guid>

					<description><![CDATA[Sometimes you just need more SWAP space on your Raspberry Pi. Per default, it is set to 100 MB if I remember correctly, which is low and depending on what you are running on your Raspberry Pi, filled up pretty...]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Sometimes you just need more SWAP space on your Raspberry Pi. Per default, it is set to 100 MB if I remember correctly, which is low and depending on what you are running on your Raspberry Pi, filled up pretty fast.</p>



<p class="wp-block-paragraph">One thing to keep in mind, your SWAP should never be higher than your actual RAM though. SWAP is not meant to serve as &#8220;extra Memory&#8221;, it&#8217;s there for cases where your machine might temporarily need a bit more than just what you have for memory.</p>



<p class="wp-block-paragraph">In my case. it&#8217;s Nextcloud. My Nextcloud is running on a 4 GB Raspberry Pi and when I scroll through my images this 4 GB RAM will be used rather fast, depending on how many images are already cached by Redis and how many thumbnails need to be generated. So it&#8217;s starting to use SWAP space and I can assure you, the default setting was not enough here and the system ran into an OOM (Out Of Memory) rather fast. Live image manipulation seems to use quite some memory, so increasing the SWAP it was and I opted to set it to 4 GB as well.</p>



<p class="wp-block-paragraph">First, you need to deactivate the current SWAP.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
sudo dphys-swapfile swapoff
</pre></div>


<p class="wp-block-paragraph">Now modify the SWAP size by editing the <code>/etc/dphys-swapfile</code>. You find the variable <code>CONF_SWAPFILE</code> there. Set it to the size you like to have, like so:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
CONF_SWAPSIZE=4096
</pre></div>


<p class="wp-block-paragraph">If you plan on using more than 2 GB of SWAP space, you might have to comment in and change the <code>CONF_MAXSWAP</code> variable as well. and set it to the new SWAP size. <code>CON_MAXSWAP</code> is set to 2 GB as default and as the name already suggests, this is the maximum of SWAP space the system will reserve.</p>



<p class="wp-block-paragraph">Now, re-create the SWAP file with:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
sudo dphys-swapfile setup
</pre></div>


<p class="wp-block-paragraph">And start the SWAP again with:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
sudo dphys-swapfile swapon
</pre></div>


<p class="wp-block-paragraph">That&#8217;s all, quick and easy.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://ppfeufer.de/raspberry-pi-change-swap-size/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Quick Update Script for Your Docker Containers</title>
		<link>https://ppfeufer.de/quick-update-script-for-your-docker-containers/</link>
					<comments>https://ppfeufer.de/quick-update-script-for-your-docker-containers/#respond</comments>
		
		<dc:creator><![CDATA[H. Peter Pfeufer]]></dc:creator>
		<pubDate>Sun, 22 Jan 2023 13:18:57 +0000</pubDate>
				<category><![CDATA[Docker]]></category>
		<category><![CDATA[Bash]]></category>
		<category><![CDATA[Bash Script]]></category>
		<category><![CDATA[Linux]]></category>
		<guid isPermaLink="false">https://ppfeufer.de/?p=31117</guid>

					<description><![CDATA[From time to time, you need to update your docker containers. And when built with docker-compose I have a little update-script for you. Nothing incredibly magical here, just a script that runs through the update commands and restarts the container...]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">From time to time, you need to update your docker containers. And when built with <code>docker-compose</code> I have a little update-script for you. Nothing incredibly magical here, just a script that runs through the update commands and restarts the container afterwards.</p>



<p class="wp-block-paragraph">However, I assume your docker container is defined through a <code>docker-compose.yaml</code> file and built with <code>docker-compose</code>.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
#!/usr/bin/env bash

CWD=$(pwd)

# Make sure we are in the current directory with this script
cd $CWD

# Check for docker-compose.yaml file
if &#x5B;&#x5B; -f &quot;docker-compose.yml&quot; || -f &quot;docker-compose.yaml&quot; ]]
    then
        # Updae docker containers
        docker-compose pull

        # Restart docker containers
        docker-compose down
        docker-compose up -d
    else
        echo &quot;&#039;docker-compose.yaml&#039; not found, exiting.&quot;
        exit 1
fi
</pre></div>


<p class="wp-block-paragraph">Save this script and make it executable.<br>To update, run this script in the directory where the containers <code>docker-compose.yaml</code> is located.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://ppfeufer.de/quick-update-script-for-your-docker-containers/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>SearXNG &#8211; Build Your Own Search Engine</title>
		<link>https://ppfeufer.de/searxng-build-your-own-search-engine/</link>
					<comments>https://ppfeufer.de/searxng-build-your-own-search-engine/#comments</comments>
		
		<dc:creator><![CDATA[H. Peter Pfeufer]]></dc:creator>
		<pubDate>Wed, 14 Dec 2022 03:21:21 +0000</pubDate>
				<category><![CDATA[Self-Hosted Service]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Privacy]]></category>
		<category><![CDATA[Raspberry PI]]></category>
		<category><![CDATA[Search Engine]]></category>
		<category><![CDATA[SearXNG]]></category>
		<guid isPermaLink="false">https://ppfeufer.de/?p=31087</guid>

					<description><![CDATA[Well, I have to admit, the title is a bit clickbait. You don&#8217;t build your own search engine per se, instead, you use an already-built open-source solution. All you need is your own server, VPS, Raspberry Pi or whatever you...]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Well, I have to admit, the title is a bit clickbait. You don&#8217;t build your own search engine per se, instead, you use an already-built open-source solution. All you need is your own server, VPS, Raspberry Pi or whatever you have. Heck, you can even run this locally on your Linux machine.</p>



<p class="wp-block-paragraph">Reasons for hosting a search engine on your own are plenty, but mostly it&#8217;s about privacy. Google and other search provider collect a metric boatload of information with every search you run through them. And there is no need to feed them. What you search for should only concern you, after all.</p>



<p class="wp-block-paragraph">SearXNG is a so-called meta-search engine. Which is nothing else but fancy speak for it&#8217;s asking multiple other search engines to get you the search result. And by self-hosting it, all privacy-related data and information stay with you and the other search engines only get the IP of the server you are hosting it on. Nothing else.</p>



<p class="wp-block-paragraph">So, let&#8217;s dive into this endeavour and get it set up, shall we?</p>



<h2 class="wp-block-heading">Prerequisites and Preparing the System</h2>



<p class="wp-block-paragraph">As mentioned, you need some hardware to host this. If you already have a server hosting your website, this will do. A small 3 €/month VPS from a hoster will do as well, even the Raspberry Pi on your desk will do.  For the latter, you need to do some port forwarding in your router if you want to access it from outside of your local network, but I&#8217;m sure you know how to do this, am I right?</p>



<p class="wp-block-paragraph">With this out of the way, let&#8217;s get to it. SSH into your server and make sure everything is up-to-date.</p>



<p class="wp-block-paragraph">Hint: System-relevant commands in this article are for Debian-based systems, so you might have to translate this to whatever distribution you use.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
sudo apt update
sudo apt upgrade
</pre></div>


<p class="wp-block-paragraph">Now, let&#8217;s install Docker if not already installed.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
sudo apt install docker.io docker-compose
</pre></div>


<h2 class="wp-block-heading">Install SearXNG</h2>



<p class="wp-block-paragraph">From this point on, please make sure you are not using <code>root</code> as the user, use your unprivileged system user. Using <code>root</code> for everything is just a lousy manner. So <code>su</code> into your user and <code>cd</code> into the home directory, we&#8217;ll be working in there.</p>



<p class="wp-block-paragraph">The easiest way is to clone the SearXNG docker repository from GitHub and make the needed changes there.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
git clone git@github.com:searxng/searxng-docker.git
</pre></div>


<p class="wp-block-paragraph">Now, <code>cd</code> into the <code>searxng-docker</code> directory.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
cd searxng-docker
</pre></div>


<p class="wp-block-paragraph">The first file you should edit is the <code>.env</code> file. This file holds the hostname and your email address for Let&#8217;s Encrypt if you like to use HTTPS, and there is no reason not to do so.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
nano .env
</pre></div>


<p class="wp-block-paragraph">Set the variables there accordingly and save the file.</p>



<p class="wp-block-paragraph">Feel free to also have a quick look at the docker-compose.yml file, but usually, you don&#8217;t need to change anything in there.</p>



<p class="wp-block-paragraph">Next, you generate a secret key, which is used to do some encryption.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
sed -i &quot;s|ultrasecretkey|$(openssl rand -hex 32)|g&quot; searxng/settings.yml
</pre></div>


<p class="wp-block-paragraph">The last file that needs to be edited is <code>searxng/settings.yml</code>.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
nano searxng/settings.yml
</pre></div>


<p class="wp-block-paragraph">In this file, you can customise your search engine. You can give it its own name, tell it which search engines it should use to get the search results for you and so on. I recommend at least giving it its own name and letting it know to use <code>GET</code> instead of <code>POST</code> (Default) for search queries.</p>



<p class="wp-block-paragraph">To do so, add the following to their respective sections. If a section is not already defined, you can simply add it.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: yaml; title: ; notranslate">
server:
  method: &quot;GET&quot;
ui:
  static_use_hash: true
redis:
  url: redis://redis:6379/0
general:
  debug: false
  instance_name : &quot;Not Google&quot;
  contact_url: false
</pre></div>


<p class="wp-block-paragraph">For a deeper dive into the settings, feel free to have a look at the <a href="https://docs.searxng.org/admin/settings/index.html" target="_blank" rel="noreferrer noopener">documentation here</a>.</p>



<p class="wp-block-paragraph">Now that everything is configured, time to start it. To do so, simply run:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
sudo docker-compose up -d
</pre></div>


<p class="wp-block-paragraph">If everything went according to plan, you should now be able to access your very own search engine under the URL you defined earlier.</p>



<p class="wp-block-paragraph">Have fun!</p>
]]></content:encoded>
					
					<wfw:commentRss>https://ppfeufer.de/searxng-build-your-own-search-engine/feed/</wfw:commentRss>
			<slash:comments>3</slash:comments>
		
		
			</item>
		<item>
		<title>PrivateBin &#8211; Your Self-Hosted Pastebin Instance</title>
		<link>https://ppfeufer.de/privatebin-your-self-hosted-pastebin-instance/</link>
					<comments>https://ppfeufer.de/privatebin-your-self-hosted-pastebin-instance/#comments</comments>
		
		<dc:creator><![CDATA[H. Peter Pfeufer]]></dc:creator>
		<pubDate>Mon, 07 Nov 2022 08:22:53 +0000</pubDate>
				<category><![CDATA[Self-Hosted Service]]></category>
		<category><![CDATA[Pastebin]]></category>
		<category><![CDATA[Privacy]]></category>
		<category><![CDATA[PrivateBin]]></category>
		<guid isPermaLink="false">https://ppfeufer.de/?p=31059</guid>

					<description><![CDATA[A Pastebin is a quick and handy way to share logs, debug output, etc. They are usually used in support situations. There are quite several public Pastebin services out there, with the most known being pastebin.com. But they all have...]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">A Pastebin is a quick and handy way to share logs, debug output, etc. They are usually used in support situations. There are quite several public Pastebin services out there, with the most known being <a rel="noreferrer noopener" href="https://pastebin.com/" target="_blank">pastebin.com</a>. But they all have one issue, privacy. You have to trust the hoster with your data. And logs can reveal a lot of information.</p>



<p class="wp-block-paragraph">Wouldn&#8217;t it be nice to host such a service yourself? PrivateBin to the rescue!</p>



<p class="wp-block-paragraph">This article will showcase how easy it is to host your own PrivateBin instance. Some assumptions are being made here of course, such as that you have a server to run your PrivateBin instance, your own domain to go with and are confident to get SSL certificates to work because it&#8217;s 2022 and there is no reason not to have your website not running with HTTPS.</p>



<p class="wp-block-paragraph">In this article, I walk you through both, bare-metal installation and docker-compose.</p>



<h2 class="wp-block-heading">Bare-Metal Installation</h2>



<h3 class="wp-block-heading">Requirements</h3>



<p class="wp-block-paragraph">To run PrivateBin you need PHP installed. According to the official documentation of PrivateBin, PHP 7.0 at least, but again, it&#8217;s 2022, so best go with a more recent version here. I recommend using PHP 8.1, you can have a quick read-up here on how to <a href="https://ppfeufer.de/raspberry-pi-install-php-8-1/">install PHP 8.1 on Debian-based systems</a> such as your Raspberry Pi for example.</p>



<p class="wp-block-paragraph">Furthermore, you need some PHP extensions, such as:</p>



<ul class="wp-block-list">
<li>GD extension</li>



<li>zlib extension</li>
</ul>



<p class="wp-block-paragraph">You also need some disk space or a database supported by <a rel="noreferrer noopener" href="https://www.php.net/manual/en/book.pdo.php" target="_blank">PDO</a>.</p>



<h3 class="wp-block-heading">Install PrivateBin</h3>



<p class="wp-block-paragraph">The installation process is pretty straightforward.</p>



<p class="wp-block-paragraph">Download the <a rel="noreferrer noopener" href="https://github.com/PrivateBin/PrivateBin/releases/latest" target="_blank">latest release from the release archive</a> (It&#8217;s the link labelled &#8220;Source Code (&#8230;)&#8221;) and extract it in the folder you want to install your PrivateBin instance. For example <code>/var/www/privatebin/</code>. Ensure the files and folders are owned by the `www-data` user so your webserver can read and write there.</p>



<h3 class="wp-block-heading">Configure PrivateBin</h3>



<p class="wp-block-paragraph">An example configuration is provided in <code>cfg/conf.sample.php</code> which you can copy to <code>cfg/conf.php</code>. The file&#8217;s content is well documented and explained in the file itself, change it to your needs. Important to know is that <code>basepath</code> is mandatory to configure with the URL of your PrivateBin instance, including the full protocol (`https://`) and it needs to have a trailing slash.</p>



<h3 class="wp-block-heading">Configure the Webserver</h3>



<p class="wp-block-paragraph">I use Nginx for this, which I will cover here. For Apache2 users, I&#8217;m pretty sure you know how to write a vhost file pointing at a directory. There is no rocket science involved in this one, just have it pointing to the right directory.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
server {
    listen 80;
    listen &#x5B;::]:80;

    server_name pastebin.yourdomain.net;

    # Redirect all HTTP requests to HTTPS with a 301 Moved Permanently response.
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    listen &#x5B;::]:443 ssl http2;

    server_name pastebin.yourdomain.net;

    ssl_certificate         /certificates/pastebin.yourdomain.net.crt;
    ssl_certificate_key     /certificates/pastebin.yourdomain.net.key;

    include /etc/nginx/options-ssl-nginx.conf;

    gzip on;
    access_log  /var/log/nginx/pastebin.yourdomain.net/access.log;
    error_log   /var/log/nginx/pastebin.yourdomain.net/error.log  warn;

    root /var/www/pastebin;
    index index.php index.html index.htm index.nginx-debian.html;

    location / {
        try_files $uri $uri/ =404;
    }

    # In case you are running PHP-FPM, uncomment the following lines
#    location ~ .php$ {
#        include snippets/fastcgi-php.conf;
#        fastcgi_pass unix:/var/run/php/php-fpm.sock;
#    }
}
</pre></div>


<h2 class="wp-block-heading">Docker-Compose Installation</h2>



<h3 class="wp-block-heading">Requirements</h3>



<p class="wp-block-paragraph">Same as for the bare-metal installation, we need to install some software packages, this time to run docker images. Let&#8217;s dive right into it and install <code>docker</code> and <code>docker-compose</code>.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
sudo apt install docker.io docker-compose
</pre></div>


<p class="wp-block-paragraph">That&#8217;s all the software you need to install. The next step is to prepare the docker-compose file so Docker knows what to do.</p>



<h3 class="wp-block-heading">The Docker-Compose File</h3>



<p class="wp-block-paragraph">This file is pretty much a description file for Docker and holds information about what to download, how to name the container and so on. I&#8217;m not going into too much detail here, when you chose a Docker install you probably know what this is all about.</p>



<p class="wp-block-paragraph">So, pick a nice spot on your favourite drive, I like to have my docker stuff in <code>~/docker/</code> for example, so it&#8217;s nice and easy to find, and create a file called <code>docker-compose.yml</code> and paste the following in.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: yaml; title: ; notranslate">
version: &quot;3.7&quot;

services:
  privatebin:
    image: privatebin/nginx-fpm-alpine:latest
    container_name: privatebin
    read_only: true
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=Etc/UTC
    volumes:
      - &#039;./privatebin-data:/srv/data&#039; # data volume for pastes
      - &#039;./conf.php:/srv/cfg/conf.php:ro&#039; # second volume for custom configuration file
    ports:
      - 3007:8080
    restart: always
</pre></div>


<p class="wp-block-paragraph">Of course, you can set port 3007 to whatever you like, just make sure you remember what you set it to and that no other service is already listening in this port.</p>



<p class="wp-block-paragraph">Before we start up the Docker volume, one additional file needs to be created, <code>conf.php</code>. This file holds the configuration for your PrivateBin instance. To do so, simply download the configuration example from the official PrivateBin GitHub repository.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
wget -O conf.php https://raw.githubusercontent.com/PrivateBin/PrivateBin/master/cfg/conf.sample.php
</pre></div>


<p class="wp-block-paragraph">This is your configuration file, you definitely should have a look through it right about now and set things up accordingly.</p>



<h3 class="wp-block-heading">Nginx as Reverse Proxy</h3>



<p class="wp-block-paragraph">Next on the list of things to do is to set up the Nginx reverse proxy. Create a new vhost file and paste in the following.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; highlight: [41]; title: ; notranslate">
server {
    listen 80;
    listen &#x5B;::]:80;

    server_name pastebin.yourdomain.net;

    # Redirect all HTTP requests to HTTPS with a 301 Moved Permanently response.
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    listen &#x5B;::]:443 ssl http2;
    
    server_name pastebin.yourdomain.net;

    ssl_certificate         /certificates/pastebin.yourdomain.net.crt;
    ssl_certificate_key     /certificates/pastebin.yourdomain.net.key;

    include /etc/nginx/options-ssl-nginx.conf;

    add_header          X-Xss-Protection            &quot;1; mode=block&quot; always;
    add_header          X-Content-Type-Options      &quot;nosniff&quot; always;
    add_header          Strict-Transport-Security   &quot;max-age=15552000; preload&quot; always;
    add_header          X-Frame-Options             &quot;SAMEORIGIN&quot; always;
    add_header          &#039;Referrer-Policy&#039;           &#039;origin-when-cross-origin&#039;;
    add_header          Content-Security-Policy     &quot;frame-ancestors yourdomain.net pastebin.yourdomain.net;&quot;;
    add_header          X-XSS-Protection            &quot;1; mode=block&quot; always;

    proxy_hide_header   X-Powered-By;
    proxy_buffering     off;                        ## Sends data as fast as it can not buffering large chunks.

    gzip on;
    access_log  /var/log/nginx/pastebin.yourdomain.net.access.log;
    error_log   /var/log/nginx/pastebin.yourdomain.net.error.log  warn;

    location / {
        proxy_set_header   X-Real-IP $remote_addr;
        proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header   Host $host;
        proxy_pass         http://localhost:3007/;
        proxy_http_version 1.1;
        proxy_set_header   Upgrade $http_upgrade;
        proxy_set_header   Connection &quot;upgrade&quot;;
    }
}
</pre></div>


<p class="wp-block-paragraph">As you can see in line 41, this is where you need the port from your <code>docker-compose.yml</code> file.</p>



<p class="wp-block-paragraph">One thing you have to keep in mind, PasteBin will only run with SSL, so make sure you have that Let&#8217;s Encrypt certificate configured.</p>



<h3 class="wp-block-heading">Start the Show</h3>



<p class="wp-block-paragraph">When you have saved your vhost file and activated it, go back to your docker directory and run the following command.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
docker-compose up -d
</pre></div>


<p class="wp-block-paragraph">If everything is correct, you should now be able to access your new PrivateBin instance in your browser.</p>



<h3 class="wp-block-heading">Fix Permissions</h3>



<p class="wp-block-paragraph"><em>(This only applies when you have selected file storage for your pastes in your <code>conf.php</code>.)</em></p>



<p class="wp-block-paragraph">Unfortunately, you cannot yet save pastes, there are still some permissions that need to be fixed. It&#8217;s a bit fiddling around, but not that much.</p>



<p class="wp-block-paragraph">First, make sure the <code>privatebin-data</code> directory is globally writeable. Don&#8217;t worry, we change that again, we just need the Docker instance to be able to write into it, so we can see what user and group it&#8217;s using.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
sudo chmod 777 privatebin-data/
</pre></div>


<p class="wp-block-paragraph">Now open your PrivateBin website and create a paste. This will now write some data into the directory and you can check for the user and group.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
ls -rtlh privatebin-data/
</pre></div>


<p class="wp-block-paragraph">For me, this was the result:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
» sudo ll privatebin-data/
total 32K
drwx------ 3 nobody 82 4.0K May 13 21:12 3c
drwx------ 3 nobody 82 4.0K May 13 21:08 4f
drwx------ 3 nobody 82 4.0K May 13 21:02 66
drwx------ 3 nobody 82 4.0K May 13 20:59 86
drwx------ 3 nobody 82 4.0K May 13 21:00 ae
-rw-r----- 1 nobody 82   45 May 13 21:12 purge_limiter.php
-rw-r----- 1 nobody 82  522 May 13 20:59 salt.php
-rw-r----- 1 nobody 82  132 May 13 21:12 traffic_limiter.php
</pre></div>


<p class="wp-block-paragraph">As you can see, the user is <code>nobody</code> and the group is <code>82</code> in my case. So the next step will be to fix the permissions for the <code>privatebin-data</code> directory.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
sudo chown -R nobody:82 privatebin-data/
sudo chmod 700 privatebin-data/
</pre></div>


<p class="wp-block-paragraph">This should take care of the permission issue and PrivateBin should now be able to write into the data directory without issues and without it being globally writeable.</p>



<p class="wp-block-paragraph">That&#8217;s it, have fun with your own Pastebin service!</p>
]]></content:encoded>
					
					<wfw:commentRss>https://ppfeufer.de/privatebin-your-self-hosted-pastebin-instance/feed/</wfw:commentRss>
			<slash:comments>5</slash:comments>
		
		
			</item>
		<item>
		<title>Raspberry Pi &#8211; Install PHP 8.1</title>
		<link>https://ppfeufer.de/raspberry-pi-install-php-8-1/</link>
					<comments>https://ppfeufer.de/raspberry-pi-install-php-8-1/#respond</comments>
		
		<dc:creator><![CDATA[H. Peter Pfeufer]]></dc:creator>
		<pubDate>Fri, 04 Nov 2022 16:35:30 +0000</pubDate>
				<category><![CDATA[Raspberry Pi]]></category>
		<category><![CDATA[Apache2]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[PHP 8.1]]></category>
		<category><![CDATA[Raspberry PI]]></category>
		<guid isPermaLink="false">https://ppfeufer.de/?p=31046</guid>

					<description><![CDATA[Installing PHP on a Raspberry PI is actually pretty straightforward, PHP is available in the Raspberry&#8217;s package repository. But, at the time of this writing, Just PHP 7.4 is available. Still ok, not terribly outdated, but dropped out of active...]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Installing PHP on a Raspberry PI is actually pretty straightforward, PHP is available in the Raspberry&#8217;s package repository. But, at the time of this writing, Just PHP 7.4 is available. Still ok, not terribly outdated, but dropped out of active support on November 28th, 2021 and will be EoL with November 28th, 2022. See <a rel="noreferrer noopener" href="https://www.php.net/supported-versions.php" target="_blank">PHP Supported Versions Overview</a>.</p>



<p class="wp-block-paragraph">With this in mind, we&#8217;re going for the latest PHP version, which &#8211; at this time &#8211; is 8.1. To install this one, some minor steps are needed, nothing too big, just a couple of commands to copy/paste.</p>



<p class="wp-block-paragraph"><strong>Note:</strong> This guide is not only for Raspberry Pi and may also be used for Debian and/or Ubuntu (untested though).</p>



<h2 class="wp-block-heading">Install PHP 8.1</h2>



<p class="wp-block-paragraph">First off, the respective sources need to be added. For this, the GPG keys need to be downloaded to verify the packages.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
sudo wget -qO /etc/apt/trusted.gpg.d/php.gpg https://packages.sury.org/php/apt.gpg
</pre></div>


<p class="wp-block-paragraph">Now add the repository with:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
echo &quot;deb https://packages.sury.org/php/ $(lsb_release -sc) main&quot; | sudo tee /etc/apt/sources.list.d/php.list
</pre></div>


<p class="wp-block-paragraph">And update the package list with:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
sudo apt update
</pre></div>


<p class="wp-block-paragraph">Now, PHP 8.1 and all its extensions can be installed using <code>apt</code>.</p>



<p class="wp-block-paragraph">Example with the most common extensions:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
sudo apt install -y php8.1-common php8.1-cli php8.1-mysql php8.1-xml php8.1-curl php8.1-zip php8.1-gd php8.1-imap 
</pre></div>


<p class="wp-block-paragraph">Check which PHP version is active with:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
php --version
</pre></div>


<p class="wp-block-paragraph">Installed PHP modules/extensions can be checked with:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
php -m
</pre></div>


<h2 class="wp-block-heading">Integrate With Your Apache2 Webserver</h2>



<p class="wp-block-paragraph">To integrate PHP 8.1 with your Apache2 webserver, simply run:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
sudo apt install libapache2-mod-php8.1
</pre></div>


<p class="wp-block-paragraph">In case there is already another version of PHP used by your Apache2, the installation will return something like this:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
...
Creating config file /etc/php/8.1/apache2/php.ini with new versionlibapache2-mod-php8.1: php8.0 module already enabled, not enabling PHP 8.1
</pre></div>


<p class="wp-block-paragraph">In this case, the old PHP version needs to be disabled and the new one enabled. (In this example PHP 8.0 is the old version)</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
sudo a2dismod php8.0
sudo a2enmod php8.1
</pre></div>


<p class="wp-block-paragraph">Now the Apache2 webserver needs to be restarted, which you do with this command:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
sudo systemctl restart apache2.service
</pre></div>


<h2 class="wp-block-heading">Test PHP</h2>



<p class="wp-block-paragraph">In the public directory of your webserver (<code>/var/www/html/</code> by default) place a file called <code>phpinfo.php</code> with the following content:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: php; title: ; notranslate">
&lt;?php
phpinfo();
</pre></div>


<p class="wp-block-paragraph">Now when opening this file in your web browser the PHP info page should be returned detailing everything about the PHP installation and configuration.</p>



<p class="wp-block-paragraph">Make sure this page is not publically available though, it might expose some information of your installation you want to keep for yourself.</p>



<h2 class="wp-block-heading">Uninstall PHP</h2>



<p class="wp-block-paragraph">To completely uninstall PHP again, run the following command:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
sudo apt purge --autoremove -y php-common mime-support
</pre></div>


<p class="wp-block-paragraph">Remove GPG keys and the repository with:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
sudo rm -rf /etc/apt/trusted.gpg.d/php.gpg
sudo rm -rf /etc/apt/sources.list.d/php.list
</pre></div>


<p class="wp-block-paragraph">And last but not least, remove the <code>systemd</code> file with:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
sudo rm -rf /var/lib/systemd/timers/stamp-phpsessionclean.timer
</pre></div>]]></content:encoded>
					
					<wfw:commentRss>https://ppfeufer.de/raspberry-pi-install-php-8-1/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Raspberry Pi &#8211; Full Backup with `dd`</title>
		<link>https://ppfeufer.de/raspberry-pi-full-backup-with-dd/</link>
					<comments>https://ppfeufer.de/raspberry-pi-full-backup-with-dd/#respond</comments>
		
		<dc:creator><![CDATA[H. Peter Pfeufer]]></dc:creator>
		<pubDate>Fri, 21 Oct 2022 04:29:59 +0000</pubDate>
				<category><![CDATA[Raspberry Pi]]></category>
		<category><![CDATA[Backup]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Raspberry PI]]></category>
		<guid isPermaLink="false">https://ppfeufer.de/?p=31001</guid>

					<description><![CDATA[If you&#8217;re running a Raspberry Pi with a somewhat important service in your network, like a DNS-Level Adblocker, Nextcloud, a proxy web server and so on, you&#8217;ll probably like to back it up on a regular basis. One way could...]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">If you&#8217;re running a Raspberry Pi with a somewhat important service in your network, like a DNS-Level Adblocker, Nextcloud, a proxy web server and so on, you&#8217;ll probably like to back it up on a regular basis.</p>



<p class="wp-block-paragraph">One way could be to unplug the MicroSD card &#8211; or any other kind of storage you use &#8211; from it, plug it into your workstation and make a copy of it. While this definitely works, it will leave your Raspberry Pi offline for that time, which in return would interrupt the service it provides.</p>



<p class="wp-block-paragraph">So, a better way would be to run the backup while the Raspberry Pi is up and running. And let me tell you, this is pretty simple to do with the <code>dd</code> command.</p>



<h2 class="wp-block-heading">Some Assumptions</h2>



<p class="wp-block-paragraph">You have some sort of storage somewhere (like a NAS for example) that can be mounted via <code>cifs</code> or <code>nfs</code>, whatever flavour you like. I&#8217;ll be using <code>cifs</code> in this example.</p>



<p class="wp-block-paragraph">The backup storage is mounted to <code>/mnt/Backup/</code>, but you can mount it anywhere you like in your file system.</p>



<h2 class="wp-block-heading">Mount the Storage</h2>



<p class="wp-block-paragraph">Your <code>CIFS</code> is hopefully requiring a username and password. So you&#8217;ll need to create a credentials file first. This file is used to pass your credentials &#8211; username and password &#8211; to <code>cifs</code> during the mount process.</p>



<p class="wp-block-paragraph">For simplicities sake, we&#8217;ll have this file as <code>/home/pi/.mount-credentials/backup-storage</code> with the following content:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
username=your_cifs_user
password=your_cifs_password
</pre></div>


<p class="wp-block-paragraph">To make sure this file cannot be changed by accident, secure it:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
chmod 600 /home/pi/.mount-credentials/backup-storage
</pre></div>


<p class="wp-block-paragraph">Now, that this is done, it&#8217;s time to tell the system where we want to mount the backup storage.</p>



<p class="wp-block-paragraph">First, the mount point needs to be created. This is simply a directory where the backup storage is mounted to.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
sudo mkdir -p /mnt/Backup
</pre></div>


<p class="wp-block-paragraph">Now it&#8217;s time to mount the backup storage to its new location. Again for simplicities sake, we use the <code>/etc/fstab</code> file here. This way it&#8217;ll be mounted every time the Raspberry Pi is booting.</p>



<p class="wp-block-paragraph">To do so, add the following line to your <code>/etc/fstab</code> file:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
//my_server.lan/backup/raspberry-pi    /mnt/Backup    cifs    credentials=/home/pi/.mount-credentials/backup-storage,vers=3.0,uid=pi,gid=pi,iocharset=utf8,dir_mode=0770,file_mode=0655,noperm    0 0
</pre></div>


<p class="wp-block-paragraph">Explanation:</p>



<p class="wp-block-paragraph"><code>//my_server.lan/backup/raspberry-pi</code> is the directory on your backup storage where the backup files will be written to. Change this accordingly.</p>



<p class="wp-block-paragraph"><code>/mnt/Backup</code> is where the backup storage is mounted and can be accessed.</p>



<p class="wp-block-paragraph"><code>cifs</code> is the network filesystem we use.</p>



<p class="wp-block-paragraph">And the long line of options are options that are passed down to <code>cifs</code>, like our credentials, which user should be used, directory and file permissions, charset and so on.</p>



<p class="wp-block-paragraph">Save the file and run the following command to mount the backup storage:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
sudo mount -a
</pre></div>


<h2 class="wp-block-heading">The Backup Script</h2>



<p class="wp-block-paragraph">Now that we have taken care of the backup location, it&#8217;s time to write our little backup script. Nothing too fancy, just some lines of shell/bash script that will check if the backup storage is mounted and try to mount it if needed and create the backup file.</p>



<p class="wp-block-paragraph">But before we do so, we need to figure out which device our drive is. Luckily that&#8217;s a rather simple task, just run <code>lsblk</code> in your console and you should see something like this:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; highlight: [4]; title: ; notranslate">
pi@raspberry_pi ~ $
» lsblk
NAME   MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
sda      8:0    0 119.2G  0 disk
├─sda1   8:1    0   256M  0 part /boot
└─sda2   8:2    0   119G  0 part /
</pre></div>


<p class="wp-block-paragraph"><code>/dev/sda</code> is the device in my case. This could vary in your setup. Make sure to change it accordingly in the backup script.</p>



<p class="wp-block-paragraph">File: <code>/home/pi/raspi-backup</code></p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
#!/usr/bin/env bash


isMounted () {
    findmnt &quot;$1&quot; &gt; /dev/null;
}


run_backup () {
    # Set some variables
    DATE=`/bin/date &#039;+%Y-%m-%d&#039;`
    TIMESTAMP=&quot;$(date +%s)&quot;
    HOSTNAME=&quot;$(hostname)&quot;

    DEVICE_TO_BACKUP=&quot;/dev/sda&quot;

    BACKUP_DIR=&quot;/mnt/Backup/&quot;
    BACKUP_FILE_NAME=&quot;raspi-${HOSTNAME}-${DATE}-${TIMESTAMP}.img&quot;


    # Mount the backup directory if necessary
    if ! isMounted &quot;${BACKUP_DIR}&quot;;
        then
            sudo mount ${BACKUP_DIR}
    fi

    # Check again to see if the mount was successful.
    # If not, stop right here, something went horribly wrong
    if ! isMounted &quot;${BACKUP_DIR}&quot;;
        then
            echo &quot;Backup directory could not be mounted. Exiting here!&quot;

            exit 1;
    fi


    # Now go forth and run the backup
    echo &quot;Backing up ${DEVICE_TO_BACKUP} to ${BACKUP_DIR} as ${BACKUP_FILE_NAME} ...&quot;
    time sudo dd if=${DEVICE_TO_BACKUP} of=${BACKUP_DIR}${BACKUP_FILE_NAME} bs=1M status=progress

    # Check for PiShrink (https://github.com/Drewsif/PiShrink)
    if command -v pishrink.sh &gt; /dev/null
        then
            # Shrinking the image
            sudo pishrink.sh -rv ${BACKUP_DIR}${BACKUP_FILE_NAME}
    fi
}


run_backup
</pre></div>


<p class="wp-block-paragraph">Make sure the file is executable with:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
chmod +x /home/pi/raspi-backup
</pre></div>


<h2 class="wp-block-heading">Run the Backup</h2>



<p class="wp-block-paragraph">The backup script is ready to be tested. To run a backup simply execute the following command in your console:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
/home/pi/raspi-backup
</pre></div>


<p class="wp-block-paragraph">With this command, your backup file will be created under <code>/mnt/Backup/raspi-your_hostname-date-timestamp.img</code>. Keep in mind, we are using a network connection to the backup storage, so this might take a while, depending on the size of your MicroSD card or other storage on your Raspberry Pi.</p>



<p class="wp-block-paragraph">For my AdGuardHome Pi the output looks like this:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
pi@adguard ~ $
» ./raspi-backup
Backing up /dev/sda to /mnt/Backup/ as raspi-adguard-2022-10-21-1666324418.img ...
127969263616 bytes (128 GB, 119 GiB) copied, 1155 s, 111 MB/s
122104+1 records in
122104+1 records out
128035676160 bytes (128 GB, 119 GiB) copied, 1161.04 s, 110 MB/s

real    19m21.064s
user    0m1.766s
sys     7m48.681s
</pre></div>


<h2 class="wp-block-heading">Restore a Backup</h2>



<p class="wp-block-paragraph">To restore a backup you can use any tool that can write ISO images to a device, like the Raspberry Pi Imager for example, or Balena Etcher. The only thing you have to make sure of is that the device is large enough. You can even use the same MicroSD card again, and since you have to restore a previous version, something went wrong with the live system, so the data on this particular MicroSD is probably damaged or in any other way no longer viable anyways.</p>



<h2 class="wp-block-heading">Last Words</h2>



<p class="wp-block-paragraph">Now, you only have to make sure to always have a somewhat recent backup!</p>



<p class="wp-block-paragraph">This method is of course not limited to Raspberry Pi systems, you can apply this method to any Linux system you want. I used the Raspberry Pi here as an example to showcase how easy it is to create backups of a running system.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://ppfeufer.de/raspberry-pi-full-backup-with-dd/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Lego &#8211; Automatic SSL Certificates and HTTPS for Everyone and Everywhere</title>
		<link>https://ppfeufer.de/lego-automatic-ssl-certificates-and-https-for-everyone-and-everywhere/</link>
					<comments>https://ppfeufer.de/lego-automatic-ssl-certificates-and-https-for-everyone-and-everywhere/#respond</comments>
		
		<dc:creator><![CDATA[H. Peter Pfeufer]]></dc:creator>
		<pubDate>Mon, 15 Aug 2022 21:46:48 +0000</pubDate>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Certbot]]></category>
		<category><![CDATA[Lego]]></category>
		<category><![CDATA[Let's Encrypt]]></category>
		<category><![CDATA[SSL]]></category>
		<category><![CDATA[SSL Certificate]]></category>
		<guid isPermaLink="false">https://ppfeufer.de/?p=30943</guid>

					<description><![CDATA[Lego is a Let&#8217;s Encrypt client written in Go, hence the name. It serves as an alternative to Let&#8217;s Encrypt&#8217;s own client certbot which can be found in many Linux distribution repositories to install. It is relatively simple to handle...]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Lego is a Let&#8217;s Encrypt client written in Go, hence the name. It serves as an alternative to Let&#8217;s Encrypt&#8217;s own client <code>certbot</code> which can be found in many Linux distribution repositories to install. It is relatively simple to handle and manages SSL certificates just fine, as long as the domain is publically reachable, meaning you can reach it from anywhere by just putting it in your browser. So using <code>certbot</code> is usually fine and works for the occasion.</p>



<p class="wp-block-paragraph">But what about domains that are not public? Like for your own local development? Usually, these domains look like <code>wordpress.local</code> for example and you won&#8217;t get SSL certificates for them. That is because they only exist in your local network and <code>certbot</code> can&#8217;t reach them for its DNS challenge. In other words, <code>certbot</code> can&#8217;t verify them and cannot create an SSL certificate for them.</p>



<p class="wp-block-paragraph">Sure, you can try to trick <code>certbot</code> a bit by using a subdomain of your live domain for example and use <code>certbot</code> with the <code>--certonly</code> option. That works somehow, but the SSL certificate generated this way can&#8217;t be renewed automatically and you have to do this dance every 3 months. Pretty annoying, trust me, been there, done that.</p>



<p class="wp-block-paragraph">Now wouldn&#8217;t it be nice if there is a way to get proper SSL certificates for your local domains as well and renew them automatically? Yes, it would, and there is! Lego to the rescue!</p>



<p class="wp-block-paragraph">First off, some assumptions and preparations. This still will not work with a <code>.local</code> domain. You need a valid live domain, in my case <code>ppfeufer.de</code>. And this domain needs to be with a provider that is in Logo&#8217;s list of <a rel="noreferrer noopener" href="https://go-acme.github.io/lego/dns/" data-type="URL" data-id="https://go-acme.github.io/lego/dns/" target="_blank">DNS Providers</a>. Because what Lego does is, query your DNS provider and obtain the certificate for you.</p>



<p class="wp-block-paragraph">So, let&#8217;s play this step by step on an example in my case. My local WordPress development is <code>wp-local.ppfeufer.de</code> and I like to have an SSL certificate for it. Why? Because I&#8217;d like to test if everything works with SSL, simple as that. Also, it&#8217;s 2022, no reason not to have SSL certificates, even for local domains :-P</p>



<p class="wp-block-paragraph">Another assumption we have to make is that you are working on a Linux system. I have no idea how and even if this all will work on Windows at all. Sorry.</p>



<h2 class="wp-block-heading">Install Lego</h2>



<p class="wp-block-paragraph">First, you need to install Lego. This can be done by simply cloning their GitHub repository and installing it from there.<br>Make sure you have Golang (&gt;=1.17) installed as well, it&#8217;s needed, we&#8217;re installing a piece of software written in Go after all.</p>



<p class="wp-block-paragraph">Clone the GitHub repository into a directory of your choice with:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
git clone git@github.com:go-acme/lego.git
</pre></div>


<p class="wp-block-paragraph">Now let&#8217;s change into the repository and compile the Lego client.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
cd lego
export GO111MODULE=on
make build
</pre></div>


<p class="wp-block-paragraph">This will take a while. This command pulls all the needed Go modules and compiled the Lego client, which can be found in the <code>dist</code> directory when done.</p>



<p class="wp-block-paragraph">Now that the Lego client has been compiled, you&#8217;ll find it in the <code>dist</code> directory inside the git repository. Go ahead and make the file executable if it isn&#8217;t already (Seems to be depending on the distribution)</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
chmod +x lego
</pre></div>


<h2 class="wp-block-heading">Making It Available on the System</h2>



<p class="wp-block-paragraph">After successfully compiling the Lego client, it needs to be made available to the command prompt. This means we have to move it somewhere where it can be executed by simply typing <code>lego</code> in our console. I for once have it in <code>/usr/bin/</code>, just a personal preference.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
cd /usr/bin/
ln -s /path/to/the/legorepository/dist/lego .
</pre></div>


<p class="wp-block-paragraph">As you can see, I&#8217;m not moving the file, I just link it. This has the advantage that when I update the Lego client, I don&#8217;t have to copy or move the file again. It&#8217;s linked and with that, it will always be the up-to-date version.</p>



<h2 class="wp-block-heading">Usage</h2>



<p class="wp-block-paragraph">Now that the preparations are done, time to use the Lego client.</p>



<p class="wp-block-paragraph">Pick your DNS provider from <a rel="noreferrer noopener" href="https://go-acme.github.io/lego/dns/" data-type="URL" data-id="https://go-acme.github.io/lego/dns/" target="_blank">this list right here</a>, the one I use in this example is <a rel="noreferrer noopener" href="https://go-acme.github.io/lego/dns/hetzner/" data-type="URL" data-id="https://go-acme.github.io/lego/dns/hetzner/" target="_blank">Hetzner</a> and as you can see, there is already an example given on how to obtain the SSL certificate.</p>



<p class="wp-block-paragraph">Example:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
cd /home/your_username

HETZNER_API_KEY=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx \
lego --email your@email.com --dns hetzner --domains your.domain.com run
</pre></div>


<p class="wp-block-paragraph">Of course, you need an API key from Hetzner first, which you can create in your DNS console on Hetzner&#8217;s website. Make sure to never share this key with anyone!</p>



<p class="wp-block-paragraph">Now you&#8217;ve got an SSL certificate which you can configure your web server with.</p>



<p class="wp-block-paragraph">All you need to do is add an entry to your <code>/etc/hosts</code> file, to make sure your local machine doesn&#8217;t bother your ISP&#8217;s DNS server for the domain name and resolves it locally.</p>



<p class="wp-block-paragraph">My example:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
127.0.0.1    your.domain.com
</pre></div>


<p class="wp-block-paragraph">From now on, every time your local machine queries this domain it resolves to its local address where your web server is listening.</p>



<h2 class="wp-block-heading">Renew the Certificate</h2>



<p class="wp-block-paragraph">Let&#8217;s Encrypt SSL certificates are valid for 3 months, so it needs to be renewed regularly. For this it&#8217;s best to make use of a cron task.</p>



<p class="wp-block-paragraph">Add the following to your crontab:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
##
# Certbot for renewing SSL certificates
##
0 */6 * * * /home/your_username/.lego/renew-scripts/01_renew_certificates
</pre></div>


<p class="wp-block-paragraph">As you can see, we make use of a shell script here. Change the file name to whatever you think is best.</p>



<p class="wp-block-paragraph">The shell script we call with the cron task looks like this:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
#!/usr/bin/env bash

# Load the Hetzner API key
export HETZNER_API_KEY_FILE=/home/your_username/.lego/hetzer-api-key

LEGO_ACCOUNT_EMAIL=your@email.com
LEGO_PATH=&quot;/home/your_username/.lego&quot;
LEGO_CERTIFICATES_PATH=&quot;${LEGO_PATH}/certificates&quot;
LEGO_RENEW_DAYS=10
LEGO_DNS_PROVIDER=hetzner

CERTIFICATE_RENEWED=False


for LEGO_CERTIFICATE_NAME in `/usr/bin/lego --path ${LEGO_PATH} list --names`
    do
        original=$(date -r &quot;${LEGO_CERTIFICATES_PATH}/${LEGO_CERTIFICATE_NAME}.crt&quot;)

        /usr/bin/lego \
            --path ${LEGO_PATH} \
            --email ${LEGO_ACCOUNT_EMAIL} \
            --accept-tos \
            --dns ${LEGO_DNS_PROVIDER} \
            --domains ${LEGO_CERTIFICATE_NAME} \
            renew --days ${LEGO_RENEW_DAYS}

        actual=$(date -r &quot;${LEGO_CERTIFICATES_PATH}/${LEGO_CERTIFICATE_NAME}.crt&quot;)

        if &#x5B; &quot;${original}&quot; != &quot;${actual}&quot; ]
            then
                CERTIFICATE_RENEWED=True
        fi
    done


if &#x5B; ${CERTIFICATE_RENEWED} == True ]
    then
        systemctl restart apache2.service
fi


exit $?
</pre></div>


<p class="wp-block-paragraph">The script needs to be executable, so run:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
chmod +x /home/your_username/.lego/renew-scripts/01_renew_certificates
</pre></div>


<h2 class="wp-block-heading">Update the Lego Client</h2>



<p class="wp-block-paragraph">Updating the Lego client is pretty straightforward. All you need to do is pull the latest from GitHub and compile it again.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
cd /path/to/the/legorepository/
git pull
export GO111MODULE=on
make build
</pre></div>


<p class="wp-block-paragraph">That&#8217;s it.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://ppfeufer.de/lego-automatic-ssl-certificates-and-https-for-everyone-and-everywhere/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Raspberry Pi &#8211; Disable Bluetooth and WiFi</title>
		<link>https://ppfeufer.de/raspberry-pi-disable-bluetooth-and-wifi/</link>
					<comments>https://ppfeufer.de/raspberry-pi-disable-bluetooth-and-wifi/#respond</comments>
		
		<dc:creator><![CDATA[H. Peter Pfeufer]]></dc:creator>
		<pubDate>Thu, 04 Aug 2022 08:10:59 +0000</pubDate>
				<category><![CDATA[Raspberry Pi]]></category>
		<category><![CDATA[Bluetooth]]></category>
		<category><![CDATA[Kernel]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Raspberry PI]]></category>
		<category><![CDATA[Wifi]]></category>
		<guid isPermaLink="false">https://ppfeufer.de/?p=30930</guid>

					<description><![CDATA[By default, when setting up a Raspberry PI, Bluetooth and WiFi are enabled. This is not always what you want, especially when you don&#8217;t need either of them. So, time to disable them, because having them enabled and probably unsecured...]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">By default, when setting up a Raspberry PI, Bluetooth and WiFi are enabled. This is not always what you want, especially when you don&#8217;t need either of them. So, time to disable them, because having them enabled and probably unsecured is a potential attack vector into your network.</p>



<h2 class="wp-block-heading">Change Boot Configuration</h2>



<p class="wp-block-paragraph">First, we need to edit the boot configuration file <code>/boot/config.txt</code> and add the following lines (edit if they are already there):</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
# Disable Bluetooth
dtoverlay=disable-bt

# Disable WiFi
dtoverlay=disable-wifi
</pre></div>


<p class="wp-block-paragraph">This will disable the Bluetooth and WiFi interfaces on start-up.<br>Unfortunately, it is not that easy. Would be nice, wouldn&#8217;t it?<br>The services are still running, the kernel modules are still loaded. Both are completely unnecessary at this point, so let&#8217;s take care of that.</p>



<h2 class="wp-block-heading">Disable the Services</h2>



<p class="wp-block-paragraph">To disable the services run the following commands:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
sudo systemctl disable wpa_supplicant.service
sudo systemctl disable hciuart.service
sudo systemctl disable bluealsa.service
sudo systemctl disable bluetooth.service
</pre></div>


<h2 class="wp-block-heading">Blacklist the Kernel Modules</h2>



<p class="wp-block-paragraph">Now that the services are deactivated, it&#8217;s time to blacklist the kernel modules. To do so, open <code>/etc/modprobe.d/raspi-blacklist.conf</code> in an editor of your choice and add:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
# Disable Bluetooth
blacklist btbcm
blacklist bnep
blacklist bluetooth

# Disable WiFi
blacklist 8192cu
</pre></div>


<p class="wp-block-paragraph">As you might have guessed by the file name, this will blacklist the modules and prevent them from being loaded during the system start.</p>



<h2 class="wp-block-heading">Disable WiFi Check</h2>



<p class="wp-block-paragraph">Now, with the next login you might see a message like this:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
rfkill: cannot open /dev/rfkill: Permission denied
rfkill: cannot read /dev/rfkill: Bad file descriptor
</pre></div>


<p class="wp-block-paragraph">This is generally nothing to be worried about, as it is just the WiFi check telling you it can&#8217;t check the status of the WiFi interface. What a surprise!</p>



<p class="wp-block-paragraph">There are 2 ways to go about it. Ignore it, which you can happily do, but if you&#8217;re like me and get annoyed by it, you might want to disable the WiFi check.</p>



<p class="wp-block-paragraph">To do so, open <code>/etc/profile.d/wifi-check.sh</code> in an editor of your choice and add <code>exit 0</code> right after the first opening bracket. The file should then look like this:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; highlight: [2]; title: ; notranslate">
(
    exit 0
    export TEXTDOMAIN=wifi-check

    . gettext.sh

    if &#x5B; ! -x /usr/sbin/rfkill ] || &#x5B; ! -c /dev/rfkill ]; then
    exit 0
    fi

    if ! /usr/sbin/rfkill list wifi | grep -q &quot;Soft blocked: yes&quot; ; then
    exit 0
    fi

    echo
    /usr/bin/gettext -s &quot;Wi-Fi is currently blocked by rfkill.&quot;
    /usr/bin/gettext -s &quot;Use raspi-config to set the country before use.&quot;
    echo
)
</pre></div>


<p class="wp-block-paragraph">If for whatever reason, you don&#8217;t feel like editing yet another file, you can just throw this command in your console, and it will do exactly that:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
sudo sed -i &#039;2i\ \ \ \ \ \ \ \ exit 0&#039; /etc/profile.d/wifi-check.sh
</pre></div>


<p class="wp-block-paragraph">Now, log out and back in and the warning message should be gone. Just don&#8217;t forget to reverse this change if you ever need to activate WiFi again.</p>



<h2 class="wp-block-heading">(Optional) Remove Unused Software</h2>



<p class="wp-block-paragraph">Now that we have disabled Bluetooth and WiFi, we can also remove the software for it. This step is entirely optional, but if you like a clean system, go ahead.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
sudo apt purge bluez bluez-firmware wpasupplicant
sudo apt-get autoremove
</pre></div>


<h2 class="wp-block-heading">Reboot</h2>



<p class="wp-block-paragraph">To apply all these changes, the Raspberry PI needs to be rebooted.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
sudo reboot
</pre></div>]]></content:encoded>
					
					<wfw:commentRss>https://ppfeufer.de/raspberry-pi-disable-bluetooth-and-wifi/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Git/SVN Repository Information Displayed in the Console</title>
		<link>https://ppfeufer.de/git-svn-repository-information-displayed-in-the-console/</link>
					<comments>https://ppfeufer.de/git-svn-repository-information-displayed-in-the-console/#respond</comments>
		
		<dc:creator><![CDATA[H. Peter Pfeufer]]></dc:creator>
		<pubDate>Thu, 19 May 2022 22:51:31 +0000</pubDate>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Bash]]></category>
		<category><![CDATA[Console]]></category>
		<category><![CDATA[Git]]></category>
		<category><![CDATA[Repository]]></category>
		<category><![CDATA[SVN]]></category>
		<guid isPermaLink="false">https://ppfeufer.de/?p=30859</guid>

					<description><![CDATA[For someone who works a lot with Git repositories, it is interesting to see some basic information in the console while working on the repo. Stuff like which branch or tag is currently active. Sure, there are commands to show...]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">For someone who works a lot with Git repositories, it is interesting to see some basic information in the console while working on the repo. Stuff like which branch or tag is currently active. Sure, there are commands to show that kind of information, but after a while, it becomes tedious to have to put those in.</p>



<p class="wp-block-paragraph">So, wouldn&#8217;t it be nice if the actual command line has this information? Yes! It can be done, at least in Bash, you just need to add a little bit of code to your <code>bashrc</code> file.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
# GIT and SVN
parse_svn_repository_root() {
    svn info 2&gt;/dev/null | sed -ne &#039;s#^Repository Root: ##p&#039;
}

parse_svn_url() {
    svn info 2&gt;/dev/null | sed -ne &#039;s#^URL: ##p&#039;
}

parse_git_branch () {
    git name-rev HEAD 2&gt; /dev/null | sed &#039;s#HEAD\ \(.*\)# (git » \1)#&#039;
}

parse_svn_branch() {
    parse_svn_url | sed -e &#039;s#^&#039;&quot;$(parse_svn_repository_root)&quot;&#039;##g&#039; | awk &#039;{print &quot; (svn » &quot;$1&quot;)&quot; }&#039;
}


# Add to command prompt
if &#x5B;&#x5B; ${EUID} == 0 ]] ; then
    # root
    export PS1=&#039;\&#x5B;\033&#x5B;01;31m\]\u@\h\&#x5B;\033&#x5B;01;34m\] \W \$\&#x5B;\033&#x5B;31m\]$(parse_git_branch)$(parse_svn_branch)\&#x5B;\033&#x5B;01;34m\]\&#x5B;\033&#x5B;00m\] &#039;
else
    # normal user
    export PS1=&#039;\&#x5B;\033&#x5B;01;32m\]\u@\h\&#x5B;\033&#x5B;01;34m\] \w \$\&#x5B;\033&#x5B;31m\]$(parse_git_branch)$(parse_svn_branch)\&#x5B;\033&#x5B;01;34m\]\&#x5B;\033&#x5B;00m\] &#039;
fi
</pre></div>


<p class="wp-block-paragraph">With the next login, you&#8217;ll see the active branch and or tag information in your command line.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://ppfeufer.de/git-svn-repository-information-displayed-in-the-console/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
