Learn how to troubleshoot and resolve issues with dual monitors on KDE, especially when one monitor stops working or remains off.
Context
By default, KDE handles dual monitors well on a new installation. However, sometimes one monitor might stop working and stay off. This happened to me, and I had to fix it using xrandr and KDE's display settings.
Steps
Here is how I resolved my issue:
Run xrandr Query:
xrandr--query
This showed two activated displays.
Copy Display Names:
I identified display names from the xrandr output.
I wanted to have search functionality in this site, which is powered by Nikola SSG. After some research I decided to create a new plugin using Flexsearch and the plugin is not available in Nikola Plugin repository.
Context
I use this site a lot as personal repository of stuff I forget. This means I refer to it when I have to do something and I no longer remember what command it was. I also refer people here when they ask something I´ve already answered here. My usual workflow was to go through my articles and use the search feature from the browser, but that was not that efficient because sometimes I only remember that one phrase of that one post.
Well, this is no longer necessary because now this site has full-text search functionality, courtesy of yours truly. This is a new Nikola Plugin, under MIT License (so that you can just use it as you want) and the FlexSearch Library.
How does this work?
Great that you ask. This is a static site. That means that whenever I post a new article I have to rebuild the site to generate HTML from my source (markdown, rst, asciidoc and others) from my git repository. In other words, this site does not use any database. The search functionality has 3 steps:
When the site is build, a search:index.json is build. This index contains all the titles, slugs and body of all my articles.
There is a search box now in th main menu. This does nothing else than calling a javascript snippet, which in turn uses the FlexSearch Library, to use that search_index as input and return a list of post that matches your search query.
The small javascript snippet renders the search results in a div for you to browse.
That´s all. It is completely offline, no Google, Databases, third party services or whatever. Pretty cool, isn´t it?
Of course, I´m not the first one to think about this. There are many examples out there. These are some of them
https://www.stephanmiller.com/static-site-search/
https://snipcart.com/blog/static-site-search
https://plugins.getnikola.com/v7/localsearch/
If you are using Nikola for your site, you are welcome to give it a try.
To prevent your internet disks from being mounted with incrementing names (e.g., name1, name2) on each reboot, configure static mount points using the /etc/fstab file. This avoids conflicts with services like Docker that use bind volumes.
Context
Each time I restarted my computer running Ubuntu/Linux Mint, my additional disks were mounted with incrementing names. This breaks all symbolic links and history because another service, Docker in my case, uses the path before it is mounted.
Why was this happening? I did not care to check how were the additional internal disks being mounted. I just connected them and started to use them. To be fair, I don't restart my computer that often (around once a year, see the image below), so it took me almost a year to find this situation.
Long story short, I restarted my computer and many thing did not work anymore, and the mount points were the cause of it.
Steps to Fix the Issue
1. Find the UUID of the Disk
Use the lsblk command to list all block devices and their UUIDs:
lsblk-oNAME,FSTYPE,UUID
You can also use the disk manager in your desktop environment to find the UUID. In my case, KDE, it looks like this:
Replace <your-uuid> with the actual UUID and /mnt/your-mount-point with your desired mount point.
4. Understand the fstab Options (optional, most of the time the defaults will work)
defaults option: A shorthand for standard mount options, including:
rw (read-write)
suid (allow setuid bits)
dev (interpret device files)
exec (allow execution of binaries)
auto (can be mounted with mount -a)
nouser (only root can mount)
async (asynchronous I/O)
0 (dump): This field is used by the dump utility to decide if the filesystem needs to be dumped. 0 means ignore.
2 (pass): The order in which fsck checks the filesystem for errors during boot. 0 means don't check, 1 is reserved for the root filesystem, and 2 is for all other filesystems.
5. Create Mount Points
If you don't have the mount points already, create them:
sudomkdir-p/mnt/your-mount-point
In my case I did already have them.
6. Mount the Drives
Restart your computer or run the following command to mount the drives immediately:
sudomount-a
In my case I had to restart the system, as that was the easiest way to get everything normal again.
Side notes
As sidenote, some of the issues I had were:
Nextcloud Desktop could not sync anymore, as it did not find the destination folder.
The quick accesses on doplhin file manager were no longer correct.
all my zoxide paths were broken.
That was enough for me to fix this, as I couldn't take it anymore. :)
The GitHub Widget Shortcode Plugin for Nikola lets you embed a customizable widget showcasing a GitHub repository's details in your site.
Context
Today, I'm excited to announce that my GitHub Widget Plugin for Nikola has been merged! This plugin allows you to embed a GitHub repository widget directly into your Nikola-generated site, displaying key details of the repository.
Nikola is a static site generator that offers great flexibility. I've already written about it [a few times](https://diegocarrasco.com/categories/nikola/, and it's what's powers this site. However, embedding GitHub repository details required custom solutions—until now. My new plugin provides an easy way to integrate this functionality using a simple shortcode.
Why is this important? Because somehow I've been using GitHub more for public code, such as my espanso-compatible TextExpander Android App. Thus, I plan to have a section on this site to list such projects, and I was missing a way to show updated information from each repository.
This is a basic text expander app for android. Use it as a espanso companion app, as it parses the yaml files in espanso/match
Languages: Kotlin
⭐ Stars: 12
Forks: 1
👁 Watchers: 2
❗ Open Issues: 0
This looks a lot better than just a link 😁
How It Works
It was a bit trial and error, as I had not used the GitHub API before.
The first approach was to use requests to call the api endpoints (such as https://api.github.com/repos/{repo}/commits) to get the json response and use that. But after that I also wanted to get the latest commits and the latest release, if available. And then I got an api rate limit error, with a nice message:
{"message":"API rate limit exceeded for 2.206.40.62. (But here's the good news: Authenticated requests get a higher rate limit. Check out the documentation for more details.)","documentation_url":"https://docs.github.com/rest/overview/resources-in-the-rest-api#rate-limiting"}
That meant, of course, that I now had to get a token to avoid the error. I tried following the GitHub API Documentation for AUTH, but without success. And then it got me... there should already be a library for this... and there was.
I installed PyGithub and refactored my code to use it. That meant I removed most of my code, as I no longer had to call each endpoint on my own.
Authentication worked instantly and I no longer had the api rate limit error.
That's the short story. Now let's explain how to use this.
Installation
You need to have a working nikola setup. If you dont have one, you can check this article: link://slug/nikola-blog-setup
To install the plugin, run the following command:
nikolaplugin-igithub_widget
Optional Configuration
For enhanced API usage, add your GitHub API token to conf.py:
# Add your GitHub API token hereGITHUB_API_TOKEN='your_github_api_token_here'
This step is optional but recommended to avoid API rate limit issues.
Your personal token should allow access to the repositories and its contents. Read-only permission is enough.
Using the Shortcode
Here are some examples of how to use the shortcode in your markdown files:
// Basic Example
{{% github_widget %}}user/repo{{% /github_widget %}}
// Example with Avatar and Custom Width
{{% github_widget avatar=true max_width=400px %}}user/repo{{% /github_widget %}}
// Example with Latest Release and Commit Info
{{% github_widget avatar=true latest_release=true latest_commit=true max_width=400px %}}user/repo{{% /github_widget %}}
Customization
You can customize the widget to display various details such as the repository owner's avatar, the latest release, and the latest commit. Adjust the max_width parameter to fit the widget into your site's layout.
Visual Examples
Here's what the widgets look like with the example shortcodes:
Basic Example
With Avatar and Custom Width
With Latest Release and Commit Info
CSS Customization
To style the widget, you can use the following CSS:
The GitHub Widget Plugin for Nikola makes it easy to display detailed information about any GitHub repository on your site. With simple configuration and usage, it's a great addition for any developer's blog or project page.
Manage disk space on Debian/Ubuntu servers and Docker containers by removing unnecessary packages, cleaning up caches, and pruning Docker objects.
Context
I needed to free up space as I had a small VPS with full storage, and my notebook and desktop computers had also a really high disk usage, although I did not have that many files, but I do use a lot of docker.
After researching I did not find a guide with everything I needed (explanations included), thus here it is.
Steps
Package Manager (apt)
Remove packages that are no longer required
sudoapt-getautoremove
Clean Up APT Cache
Check the space used by the APT cache:
sudodu-sh/var/cache/apt
Clean up the APT cache:
sudoapt-getautoclean
sudoaptautoclean
Delete cache files:
sudoapt-getclean
sudoaptclean
Clear Systemd Journal Logs
Check the disk usage of systemd journal logs:
journalctl--disk-usage
Clean logs older than 3 days:
sudojournalctl--vacuum-time=3d
Docker
Docker takes a lot of space compared to vanilla servers. Check link:/slug/change-docker-data-directory-vps-optimization for a related post on the overlay2 and how to move docker data root to another volume/ drive.
Warning: This will remove all stopped containers. Refer to the documentation for more details.
dockercontainerprune# Remove all stopped containers
Use Docker Image Prune
Remove unused images (Remove all dangling images. If -a is specified, will also remove all images not referenced by any container.)
Quick note:
What are Docker Dangling Images?
Images that have no tag and are not referenced by any container source
Untagged layers that serve no purpose but still consume disk space.
Not automatically removed by Docker and need to be cleaned up manually. source
docker image prune
Use docker volume prune
Remove all unused local volumes. Unused local volumes are those which are not referenced by any containers. By default, it only removes anonymous volumes.
dockervolumeprune# remove only anonymous (unnamed) volumes
This command removes only anonymous (unnamed) volumes by default.
I am thrilled to share some exciting news about my forthcoming book "The Digital Marketer’s Playbook: How to Effectively Collaborate with Agencies, Freelancers, and Digital Marketing Experts," to be published by Apress (Springer-Nature). The book is targeted for release by the end of Q3 or Q4 2024. That's this year!
If you've followed my blog, you might recall that I initially conceived this project as a short book. My idea was to write a practical guide with the main topics related to digital marketing. It has now evolved into a comprehensive resource. Designed for professionals grounded in marketing or business and for those particularly interested in the field, it guides readers through the complexities of digital marketing, emphasizing effective collaboration with various partners. I think the title of the book is also self-explanatory. 😁
The Journey and Collaboration
The book has evolved significantly over the past few months. My first post about it marked the beginning of this journey. Since then, ten months later, I've moved away from the idea of self-publishing for this project, choosing instead to sign to go with traditional publishing. This decision came after discussing the book proposal with Shivangi Ramachandran, an Apress Senior Editor (Acquisitions), which ended with me signin with Apress (Springer-Nature).
Partnering with them and working closely with Shiva and Sowmya Thodur (Production Editor), brought about substantial changes. After signing, I received a lot of guidelines regarding the structure how the book, which made me realize that the chapters were more that just a compilation of important points and I had to elaborate on them. These changes quickly expanded the book into a comprehensive 250+ page resource. That structured approach to writing required me to rethink and rewrite many sections of the book.
Throughout this journey, I have dedicated countless hours refining the content, often late into the night. My amazing wife’s patience has been invaluable, and I cannot thank her enough for her support. Throughout the entire process, she also served as a thoughtful partner, sharing her insights and candid comments.
Additionally, the Unperfekthaus in Essen provided a perfect environment with their focus room and endless coffee, where I spent nearly three days a week until closing time last month to finish the manuscript.
I also have to thank my colleagues at MEHRKANAL, especially Miri and Mario, for enduring my questions and serving as sparring partners on several book topics. They often heard me talk about the book, perhaps more than they would have liked. Victor and Eva, who gave me detailed feedback on the first version of the Table of Content. Damian, Tom, Holger, Christian also listened to my thoughts on the book and gave their feedback. There are many others whose names escape my memory, as it's again late into the night.
Although many of them saw this as just another item on my never ending list of personal projects, I'm thrilled it has become a reality. 😎
I wrapped up the manuscript in early June, fueled by an impressive coffee intake—seriously, about 4-6 cups per session! Thanks to the patience of many, it's now in the capable hands of the Apress team for review. Can't wait to share it with you soon!
A quick preface before diving into the details
This project has not only deepened my grasp of familiar topics; it has also allowed me to enrich the manuscript with innovative content driven by the latest trends and technologies in digital marketing.
Some chapters turned out shorter than anticipated, while others demanded more detail. I focused on keeping the content both core and practical, but ultimately, you'll be the judge of that.
Stay tuned for more updates and sneak peeks of the book! I am excited to share this resource with those of you eager to master digital marketing.
If you want to be among the first to explore "The Digital Marketer’s Playbook," please fill out the form below.
What will you learn by reading the book?
This book is my effort to provide you an all-inclusive resource to enhance your understanding of digital marketing and equip you with the skills and knowledge to work effectively with various partners in the field.
My goal throughout its pages is to provide you with everything you need to communicate your requirements to your partners, understand what they do and ask the right questions when you need to. I define digital marketing as a process, and that's also how the book is structured.
Within its pages, I guide you through the foundational concepts of digital marketing. You'll grasp what digital marketing is, familiarize yourself with crucial terms like digital assets, advertising channels, and customer awareness, and learn to distinguish between walled gardens and the open internet. This knowledge will be essential for discussing your goals and your campaigns implementations with your partners. I also describe the landscape of taxes and laws regarding digital marketing and how it can impact your digital marketing efforts.
As you dive deeper, I'll show you how to set up and structure digital marketing campaigns effectively. You'll understand bid strategies, ad quality, and the importance of placements and inventory. We'll explore various campaign types and their significance, focusing on how to craft a briefing to get impactful creatives, messages, and copy to achieve marketing success and align your digital marketing initiatives with your business goals.
Finally, I offer practical examples tailored to various company types, detailing key factors to consider based on company size, resources, and business structure. I also share my perspective on using artificial intelligence in digital marketing, discussing both its benefits and risks. Additionally, I provide an overview of social media and its role in digital marketing.
Ready to dive deeper into digital marketing? Sign up below to receive updates on "The Digital Marketer’s Playbook" and access exclusive digital marketing resources.
Quick and simple WordPress Setup for Lazy Developers
I needed a fast way to set up WordPress locally. I tried various methods, but they were either too complex or didn't work. So, I created a simple, lazy solution.
This is by no way secure, but it runs on the first try 😁
The code is in this GitHub repository. Feel free to use it.
Set up a local WordPress development environment easily with Docker Compose using this repository. One command sets up WordPress with WP-CLI, MariaDB, and PHPMyAdmin, plus autogenerated aliases for quick management. A second command sources these aliases. Perfect for quick, lazy local development. Not secure for production use.
Languages: Shell
⭐ Stars: 0
Forks: 0
👁 Watchers: 1
❗ Open Issues: 0
How It Works
This setup revolves around 4 files:
1 docker-compose.yml:
This file:
Uses the latest official containers for WordPress, MariaDB, PHPMyAdmin, and WP-CLI.
Sets up a wordpress database with user and password root.
Launches a WordPress instance linked to the database.
2 setup.sh:
This script:
Detects whether you have docker-compose or docker compose and uses the correct one.
Sets your UID and GID in a .env file.
Generates an alias file for quick commands.
3 start.sh:
This script:
Creates the WordPress directory.
Sets permissions to 777 (yes, it's insecure).
Starts Docker Compose.
4 alias.sh:
Autogenerated by setup.sh or start.sh. Source it to get these aliases:
dc: Docker Compose commands.
wpcli: WP-CLI commands.
wpbackup: Backs up the database to ./backups.
wpdown: Backs up and then stops and removes containers and volumes.
Now you are good to go. You will see a new folder wordpress is created in the path you were in.
Now you can:
Check http://localhost:8000 for the WordPress site
Check http://localhost:8080 for PHPMyAdmin. User and password is root
You receive this information also when you run start.sh.
Using the Aliases
alias dc
Bring up the services:
dcup-d
Stop the services:
dcdown
Stop and remove volumes:
dcdown-v
View the status of the services:
dcps
alias wpcli
Run WP-CLI as root (it includes --allow-root):
Check WordPress version:
wpclicoreversion
Install a plugin:
wpcliplugininstallhello-dolly--activate
Update WordPress core:
wpclicoreupdate
Create a new post:
wpclipostcreate--post_title='My New Post'--post_content='This is the content of the post.'--post_status=publish
wpbackup
Back up the database to ./backups:
wpbackup
wpdown
Back up the database and files, then stop and remove everything:
wpdown
Alternatives
Here are some other methods to consider:
Local by Flywheel: User-friendly local WordPress setup with advanced features. To be fair, I completely forgot about this when I was trying to get WordPress to run locally. This is way more powerful, but you need many clicks... and you need to fill a form to download it.
DevKinsta: Offers local development with easy deployment to Kinsta hosting. I haven't tried this one.
To change the screen resolution of a VM in Hyper-V, use PowerShell. The command requires the VM name and the desired resolution.
Context
Unlike in VirtualBox, in Hyper-V I could not find a GUI option to change the screen resolution directly. Instead, I had to use PowerShell to adjust the display settings of your virtual machine.
Steps
Identify the VM Name
Find the name of your VM in Hyper-V Manager. (Search for Hyper-V Manager in the start menu to access it)
Open PowerShell
Open a PowerShell terminal on your host machine.
Execute the Command
Use the following PowerShell command, replacing "Ubuntu 22.04 LTS2" with your VM's name and adjusting the resolution as needed:
This article guides you through creating a blog using Nikola, a static site generator that supports Markdown, reStructuredText, and Jupyter Notebooks. I'll use the Bootblog theme and detail how to host the code in a private repository on GitHub or GitLab, with a preference for GitLab. Deployment steps to Cloudflare are covered in a separate article (link provided). For editing, VSCode or PyCharm is recommended, though any text editor works.
Context
Nikola is a versatile static site generator that is perfect for researchers, educators, and bloggers who want to incorporate rich content like Jupyter Notebooks into their posts. It's Python-based, easy to customize, and supports various content types.
After extensive research and testing various static site generators, I chose Nikola as my blogging platform. While Nikola may not be as trendy as some newer generators that frequently pop up in tech articles, my priority was finding a tool that offered both stability and flexibility—qualities that are sometimes overlooked in favor of following trends.
Nikola stood out for me for several reasons:
Stability: The project has been actively maintained for over eight years, indicating a mature and dependable platform.
Flexibility: Written in Python, Nikola is particularly advantageous for those involved in DevOps and Data Science. It supports a wide array of formats and markup languages including AsciiDoc, Markdown, Jupyter Notebooks, and HTML and allows importing metadata and content also from several sources (WordPress, Pelican and others). Here you have a cheat sheet for some markup languages
Extensibility: The availability of shortcodes and plugins enhances its functionality, allowing for a high degree of customization and integration. I've created some shortcodes myself for my personal use case
Deployment Versatility: It can be deployed to virtually any platform, though I personally use Cloudflare Pages for its simplicity and performance.
Version Control Friendly: The content being stored in plain formats in a Git repository (I use GitLab) means that it's not only secure but also highly manageable and version-controlled.
This combination of features makes Nikola an ideal choice for me (and I dare say for those who value a stable, extendable, and developer-friendly blogging environment).
What is a static site generator and what's the difference with normal CMSs
A static site generator (SSG) is a tool used to produce HTML websites by compiling source files written in various markup languages like Markdown or reStructuredText. Unlike traditional content management systems (CMSs) that dynamically build a page every time a user accesses it, SSGs generate (compile) all pages at once during development. This process results in a set of static HTML files which can be easily hosted and served.
Key Differences Between SSGs and Traditional CMSs
Performance: Static sites generally load faster than their CMS counterparts because they consist of simple HTML files, eliminating the need to query a database or execute server-side scripts on each request.
Security: With fewer moving parts and no database interactions, static sites are less vulnerable to common web attacks such as SQL injection and XSS (Cross-Site Scripting).
Scalability: Hosting static files is straightforward and can handle high traffic with less overhead than dynamic sites.
Cost: Static sites can be hosted on any simple web server or services like GitHub Pages and Cloudflare Pages often for free, reducing the cost associated with web hosting.
Maintenance: Static sites require less maintenance since they don’t involve managing a server or database. Updates are made by regenerating and redeploying the site, rather than through an online interface. This means you don't need to update anything, and you may use an old version forever, so long it runs locally.
However, traditional CMSs like WordPress or Drupal offer advantages in scenarios requiring frequent updates, user interaction, or complex dynamic functionalities. They provide a user-friendly interface that allows non-technical users to easily manage content and make updates in real-time without touching the underlying code. And traditional CMSs are friendlier for a normal user.
Steps
Here's how to set it up on any major operating system and prepare it for hosting on Cloudflare.
1. Install Nikola
First, you need to install Nikola. It's Python-based, so ensure Python is installed on your system.
I recommend to use a virtual environment. I usually use miniconda. You can check the install instructions here.
Once you have Python installed (with or without a virtual environment) you need to install nikola.
pipinstallNikola[extras]
2. Create Your Nikola Site
Generate your new Nikola site with:
nikolainitmysite
cdmysite
3. Configure Nikola
Edit conf.py in your site directory to set up the Bootblog theme and enable support for Markdown, reStructuredText, and Jupyter Notebooks:
# Add bootblog to your themeTHEME="bootblog"# Enable support for Markdown, reStructuredText, and Jupyter NotebooksCOMPILERS={"rest":['.rst'],"markdown":['.md'],"ipynb":['.ipynb']}
4. Setting Up Version Control
GitHub vs. GitLab
GitHub:
- More popular and widely used.
- Integrates well with other tools and services.
- Provides free private repositories with a limit on collaborators.
GitLab:
- Offers free private repositories with unlimited collaborators.
- Includes built-in CI/CD features.
- I prefer GitLab for its comprehensive DevOps capabilities.
Using GitLab
Create anew account on https://about.gitlab.com/pricing/ on the free plan and then create a new private repository in GitLab and push your site:
For updating your blog, use VSCode or PyCharm, though any text editor will suffice. These IDEs offer great support for Python and Markdown, enhancing the blogging workflow.
Nikola has a deploy command, but I prefer to use the Cloudflare pipeline to auto-publish on git push.
Conclusion
Setting up a Nikola blog is straightforward (but requires more steps than setting a blog on WordPress.com). It supports a variety of content formats and can be easily integrated into modern workflows and tools like GitLab and Cloudflare for a robust blogging setup. The best of it is that you are not dependent on a specific platform.
Check the Handbook
The handbook on https://getnikola.com/handbook.html is great and has almost everything you might need for your blog.
Check my other articles on nikola
I've writen some articles about nikola that might interest you after this one
This guide provides step-by-step instructions on installing and configuring Secure Socket Tunneling Protocol (SSTP) VPN on Ubuntu, Kubuntu, KDE Neon, and other similar distros. Whether you're using GNOME or other desktop environments, this guide covers all necessary steps, including troubleshooting tips.
Context
SSTP VPN is widely used for securely connecting to remote networks. It's especially relevant for Ubuntu-based Linux distributions, which might require different installation steps depending on the desktop environment. This guide simplifies the process, ensuring a smooth VPN setup.
Steps
For GNOME-Based Distros (Ubuntu)
1. Install SSTP Packages:
sudoaptinstallnetwork-manager-sstpsstp-client
2. Open Network Manager:
If unsure about accessing Network Manager, run:
nm-connection-editor
3. Creating a New SSTP VPN Connection:
Use Network Manager to set up a new SSTP VPN connection.
Click on the '+' sign.
Select 'Secure Socket Tunneling Protocol (SSTP)' and click 'Create'.
Enter the VPN gateway, username, and password.
Save the settings.
For Non-GNOME Distros (Kubuntu, Linux Mint, KDE Neon)
Select 'Secure Socket Tunneling Protocol (SSTP)' and click 'Create'.
Enter the VPN gateway, username, and password.
Save the settings.
4. Connecting to VPN:
Connect via your network manager (tested on KDE).
Troubleshooting
Restarting NetworkManager Services: Sometimes, it's necessary to restart network services for changes to take effect. Use sudo service network-manager restart in the terminal.