And yet despite the look on my face, you’re still talking and thinking that I care, Anonymous
NixOS is a unique, innovative, and powerful Linux distribution that leverages the Nix package manager. Unlike traditional Linux distributions that update packages and system configurations in-place, NixOS uses a purely functional and declarative approach to define the system state, reducing the risk of system breakage.
NixOS is a Linux distribution that uses the Nix package manager to handle packages and system configuration in a purely functional manner. This approach ensures that builds are reproducible and that the system state can be reliably replicated or rolled back.
sudo nix-env ‐‐rollback is a command used to revert your system to the previous configuration. It’s a powerful tool for undoing unintended changes or recovering from failed package installations. Before rolling back, consider if there’s a more targeted solution, like uninstalling specific packages or reverting configuration files.
Hugo is a popular open-source static site generator written in Go. It allows you to create fast and flexible websites using simple Markdown files.
Step 1: Add Hugo to Your NixOS Configuration, sudo vim /etc/nixos/configuration.nix:
environment.systemPackages = with pkgs; [
# Within the environment.systemPackages attribute, add hugo:
# Hugo is would be available system-wide.
hugo
];
Step 2. Save, close the file and rebuild the system: sudo nixos-rebuild switch
Step 3. Create a new site or migrate an existing Hugo site.
mkdir my-website # Decide where you want to store your Hugo projects or websites
cd my-website
# Option 1. Create a New Site.
hugo new site my-website
# It initializes a new Hugo project in the my-website folder.
# Next, you would typically add a theme, create new posts (hugo new posts/my-first-post.md), begin editing its configuration file config.yaml, etc.
# Option 2. Migrate an existing Hugo Site.
sudo cp -R /media/my-website/ ~/my-website/
# 2.1 Copy an old Hugo site from /media/my-website/ to my-website in your home directory.
sudo chown -R YOUR-USERNAME:users ~/my-website
# 2.2. After copying, you may need to change the ownership of the copied files to your normal user...
# so you can edit the files without requiring root access.
Step 4. Running the Development Server.
# To serve your Hugo site locally and see changes as you make them:
cd ~/my-website/
hugo server -D # -D includes draft content, which is convenient during development
# Then, open your web browser and navigate to http://localhost:1313/ to view, review, and debug your site.
# When you are completely satisfied, you can build the final production-ready version of your website:
hugo
# Builds the Site for Production and generate static files in the public directory.
# You can then deploy these files on any websites.
# FileZilla is a free, open-source FTP client that allows you to transfer files between your local computer and a remote server.
# It's widely used for website management.
Step 5. Building your Hugo Site, Checking for broken links and Deploying Hugo
Linkinator is a super simple site crawler and broken link checker. You may also want to check your live site for any broken links or missing images using online tools (e.g., Free Broken Link Checker, W3C Link Checker, etc.).
Edit your NixOS configuration file and install Node.js:
vim /etc/nixos/configuration.nix
[...]
environment.systemPackages = with pkgs; [
# ... other packages ...
nodejs # Add Node.js to your system packages.
];
[...]
# Rebuild your NixOS configuration
sudo nixos-rebuild switch
# Initialize npm in your project directory
cd ~/my-website
npm init -y
# This creates a package.json file, initializing your project as an npm project.
# Install Linkinator as a development dependency
npm install --save-dev linkinator
–save-dev adds Linkinator to your devDependencies in package.json. The node_modules/.bin directory will now contain the linkinator executable.
Finally, let’s build the Hugo site, deploy, and check for broken links using Linkinator.
#!/bin/sh
USER=YOUR_USERNAME
HOST=XX.XX.XX.XX
DIR=httpdocs/ # the directory on the server where your website files are served from
# 1. Clean old files locally.
# It forces deletion without prompting. It removes the existing public directory, ensuring a clean slate before building.
rm -r ./public
# 2. Build the Hugo site
hugo --gc --cleanDestinationDir --baseURL "https://justtothepoint.com/"
# Using --gc (Garbage Collection) is a good practice. It cleans up unused cache files and other artifacts, ensuring that the final output is as clean as possible.
# The --cleanDestinationDir option ensures the public directory is removed before building. It prevents outdated files from lingering and causing conflicts.
# It is redundant because whe have already removed the public directory, but having both is not harmful.
# Setting the baseURL sets the final URL for the generated site and ensures that all links and references in my site’s final build point to my production domain.
# This will produce a fresh, final set of static files ready to be uploaded to my hosting environment.
# The hugo command builds the static site but does not start a server at http://localhost:1313.
echo "Building the Hugo site..."
In summary:
This will produce a fresh, final set of static files ready to be uploaded to your hosting environment.
# 3. Deploy to the server via rsync
rsync --compress --recursive --verbose --checksum --delete -e 'ssh -p 2222' public/ ${USER}@${HOST}:~/${DIR}
# rsync only transfers changed files and ensures your remote directory matches your local directly exactly, thanks to --delete.
# --compress helps reduce bandwidth usage
# --checksum ensures a reliable and minimal upload when files haven't been changed.
# Using a non-standard SSH port -p 2222 is a good security measure.
# Ensuring public/ goes to ~/${DIR}, i.e., ~/httpdocs on the remote host is standard practice.
# 4. Check for broken links and images using Linkinator
echo "Checking for broken links and images..."
LINKINATOR_OPTIONS=( # An array of options that can be easily modified.
--include-images # Use Linkinator to scan for broken links and images, too. By default, Linkinator only check links
--skip "mailto:*" # Exclude certain types of links (e.g., mailto: links).
--verbosity error # Reduces the output to errors only.
--recurse # Full recursive scan!
--concurrency=100 # The number of connections to make simultaneously. It speeds up the process.
--timeout=60000 # 60 seconds timeout per request. We are going to add timeout and retry options to ensure all pages are checked.
--retry=3 # Retry 3 times before giving up
--format json # Output the results in JSON Format.
)
npx linkinator ./public "${LINKINATOR_OPTIONS[@]}"
# It scans all files in the public/ directory. It follows links and checks for HTTP errors (like 404 Not Found).
echo "Link check completed successfully."
# 5. Optionally, check the live site
npx linkinator http://justtothepoint.com "${LINKINATOR_OPTIONS[@]}" > linkinator_results.json # Check the entire website and save results to a file.
echo "Link check on production site completed. Results saved to linkinator_results.json"
# 6. Additionally, install and run htmltest for deeper checks
nix-shell -p htmltest
# htmltest runs your HTML output through a series of checks to ensure all your links, images, scripts references work, your alt tags are filled in, etc.
When you are using Hugo’s development server, creating or editing your content, and notice that changes do not appear in your browser:
hugo server ‐‐noHTTPCache ‐‐disableFastRender ‐‐gc ‐‐cleanDestinationDir
‐‐gc performs garbage collection, removing unnecessary files; ‐‐cleanDestinationDir: cleans the output directory before building, ensuring no stale files remain.
Using SSH keys to authenticate is typically more secure and eliminates the need to manually type a password each time you connect.
Generate your public and private keys on your local maching: ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_rsa
where -t rsa specifies the RSA algorithm; -b 4096 sets a (more secure) 4096-bit key length; -f ~/.ssh/id_rsa writes the private key to ~/.ssh/id_rsa and the corresponding public key to ~/.ssh/id_rsa.pub.
Copy your public key to the remote server. One manual method involves copy the entire content of your public key (cat ~/.ssh/id_rsa.pub, local) and paste it into ~/.ssh/authorized_keys on the remote server.
You could use FileZilla or any other FTP client to download the file, add your public key, and then upload it again to the server. Alternatively, you can use ssh-copy-id -i ~/.ssh/id_rsa.pub YOUR-USER@YOUR-SERVER
Once your public key is in place on the server on ~/.ssh/authorized_key, you can connect: ssh -p 2222 YOUR-USER@YOUR-SERVER
or rsync --compress --recursive --verbose --checksum --delete -e 'ssh -p 2222' public/ ${USER}@${HOST}:~/${DIR}
and no longer need a password for authentication.
Some servers are configured to use non-standard ports (other than the default port 22) to enhance security and reduce the risk of automated attacks. Always check with your server administrator if a custom port is required.
Linkinator is a handy broken link checker, but it can sometimes yield confusing results.
Below is an example snippet.
🏊♂️ crawling http://localhost:1313
[0] https://polyfill.io/v3/polyfill.min.js?features=es6
http://localhost:1313/calculus/functionscalculusc/
[0] https://polyfill.io/v3/polyfill.min.js?features=es6
ERROR: Detected 1 broken links. Scanned 7951 links in 22.873 seconds.
nmaximo7 on nixos ~/justtothepoint is 📦 v1.0.0 via v20.17.0 took 1m
Potential causes:
We may need to consider: update to the latest version or remove it if you no longer need it; checking if the service require authentication or API keys; and hosting the file locally if possible.
MathJax was a popular choice for rendering mathematical equations on the web, but there are now other alternatives like KaTeX that you can use in your Hugo project. KaTeX is known for its speed and efficiency in rendering math.
Step 1. We need to remove Mathjax partial: /layouts/partials/mathjax.html.
Step 2. Remove the Mathjax partial call from the head section (often in /layouts/partials/head.html):
# Delete or comment the line
{{ if .Params.mathjax }}{{ partial "mathjax.html" . }}{{ end }}
Step 3. Remove the mathjax parameter from your content front-matter because we are no longer able to use MathJax to render our LaTex formulas in the browser. If your content front matter has a line like mathjax:true
remove or replace it with math: true
to use KaTeX.
The script below demonstrates how to programmatically replace mathjax: true
with math: true
in all Markdown files in a directory. It uses the PyYAML library (pip install pyyaml). PyYAML is a library that allows you to load, parse, and write YAML, much like Python’s JSON library helps you to work with JSON.
# Python script that safely replaces mathjax: true with math: true in the front matter of your Markdown files.
# Uses PyYAML to parse YAML front matter and safely update keys.
#!/usr/bin/env python3
# Import necessary modules
import os # For file and directory operations
import yaml # For parsing YAML front matter safely.
def process_markdown_file(filepath):
# Open the Markdown file and read its content
with open(filepath, 'r', encoding='utf-8') as f:
content = f.read() # Reads the file content.
# Split the content into front matter and the rest
if content.startswith('---'):
parts = content.split('---', 2) # Split on the first two occurrences of '---'
if len(parts) >= 3:
# The front matter is between the first two '---'
_, front_matter_raw, rest_of_content = parts[0], parts[1], parts[2]
else:
# Malformed front matter (not enough parts)
return
else:
# No front matter present
return
# Parse the front matter using YAML. This ensures that the YAML is parsed safely and correctly.
try:
front_matter = yaml.safe_load(front_matter_raw)
# After execution, the safe_load() method returns a dictionary containing the front matter
except yaml.YAMLError as exc:
print(f"Error parsing YAML in file {filepath}: {exc}") # Print error if YAML parsing fails and skips that file
return
if not isinstance(front_matter, dict):
# Ensure that the front matter is a dictionary
return
# Check if 'mathjax' key exists in the front matter.
if 'mathjax' in front_matter:
# Replace 'mathjax' key with 'math'. The script preserves all other fields in the front matter.
# Only the mathjax field is replaced with math. The pop() method removes 'mathjax' from the dict.
# The value associated with mathjax is preserved and assigned to math.
front_matter['math'] = front_matter.pop('mathjax')
# Write the updated front matter back to the file
new_front_matter_raw = yaml.safe_dump(front_matter, sort_keys=False) # Convert dict back to YAML
new_content = '---\n' + new_front_matter_raw + '---' + rest_of_content # Reconstruct the file full content
# Open the file for writing and save the updated content
with open(filepath, 'w', encoding='utf-8') as f:
f.write(new_content)
print(f"Updated file: {filepath}") # Print confirmation of the updated file
else:
# 'mathjax' key not found, do nothing
pass
def main():
# Change this to the directory containing your Markdown files
markdown_directory = '~/your-website/' # Set the directory to scan for Markdown files
# Walk recursively through all files in the directory containing the Markdown files (Hugo project)
for root, dirs, files in os.walk(markdown_directory):
for file in files:
if file.endswith('.md') or file.endswith('.markdown'):
filepath = os.path.join(root, file) # Construct the full file path
process_markdown_file(filepath) # Process each Markdown file
if __name__ == '__main__':
main() # Execute the main function when the script is run