Posts in category “Tutorial”

指南:添加 HappyNotes web到手机桌面

很多人不喜欢web app是因为要先打开浏览器再输入相应的网址,然而这一繁琐步骤是可以免去的,你完全可以像使用原生app一样使用web app。 我个人更喜欢web app,因此特意在这里告诉潜在的HappyNotes用户,只需几秒钟,你就能将它固定在手机桌面上,不论看起来还是用起来都像一个真正的移动App。

为什么 Webapp 如此棒

在介绍安装步骤前,我先啰嗦几句为什么 webapp 很酷:

  • 你永远在使用最新版本,无需手动更新
  • 体积小得令人惊讶
  • 跨设备使用,随时随地
  • 不受应用商店审核限制

iPhone 用户安装指南 📱

  1. 在 Safari 浏览器中打开 HappyNotes, 网址 https://happynotes.shukebeta.com
  2. 点击分享按钮(带箭头的方形图标)
  3. 向下滚动,选择"添加到主屏幕"
  4. 给它起个喜欢的名字(比如"HappyNotes")
  5. 点击"添加" - 大功告成!

Android 用户安装指南 🤖

  1. 打开 Chrome 浏览器,进入 HappyNotes, 网址 https://happynotes.shukebeta.com
  2. 点击菜单(三个点)或查找"+"图标
  3. 选择"添加到主屏幕"
  4. 为快捷方式命名
  5. 点击"添加" - 搞定!

现在,你可以直接从主屏幕点击 HappyNotes。随时随地,记你想记!

Howto: Add HappyNotes web to your phone's home screen

Ever wanted to use HappyNotes but thought it seemed complicated? This guide helps you add this webapp to your phone's home screen in just a few seconds, making it feel just like a native app!

Why Webapps Are Actually Amazing

Before we dive into installation, let me share why webapps like HappyNotes are fantastic:

  • Always use the latest version automatically
  • Zero download size (no massive app store downloads!)
  • Work across all devices

For iPhone Users 📱

  1. Open HappyNotes in Safari
  2. Tap the share button (square with an arrow pointing up)
  3. Scroll and select "Add to Home Screen"
  4. Name it as you like (e.g., "HappyNotes")
  5. Tap "Add" - done!

For Android Users 🤖

  1. Open Chrome and navigate to HappyNotes
  2. Tap the menu (three dots) or look for a "+" icon
  3. Choose "Add to Home Screen"
  4. Name your shortcut
  5. Tap "Add" - you're all set!

Pro tip: The icon will look just like a regular app icon. Your friends won't even know the difference! 😉

Now you can tap HappyNotes directly from your home screen, just like any other app. Enjoy seamless, always-updated note-taking wherever you go!

移动介质上的Linux:使用 tmpfs、关闭 atime 以延长 SD 卡或优盘的使用寿命

我有一台老旧的 Asus C100P Chromebook,Google早在几年前就停止了对它的支持。它是32位ARM CPU,因此我没法替它更换BIOS,但我可以在developer mode下启用优盘启动,这样我就能够在优盘或者sd卡运行Linux。

然而,在使用 SD 卡或其他闪存设备作为操作系统存储时,合理管理写入操作至关重要。本文将介绍如何通过使用 tmpfs 文件系统、关闭 atime 来延长设备的使用寿命。

1. 使用 tmpfs

什么是 tmpfs?

tmpfs 是一种基于内存的临时文件系统,具有以下优点:

  • 高速存储: 数据存储在内存中,读写速度极快。
  • 动态大小: 根据实际使用情况动态分配内存,不会固定占用资源。
  • 减少写入: 适合存储临时文件和日志,显著减少对闪存的写入操作。

如何配置 tmpfs

1.1 编辑 /etc/fstab 文件

打开终端并输入:

sudo nano /etc/fstab

添加以下行以创建 tmpfs 挂载点:

tmpfs /tmp tmpfs defaults,noatime,mode=1777 0 0
tmpfs /var/log tmpfs defaults,noatime,mode=0755 0 0

1.2 挂载 tmpfs

保存文件后,运行以下命令使更改生效:

sudo mount -a

1.3 验证挂载

使用以下命令确认 tmpfs 是否成功挂载:

df -h

您应该能看到类似于 /tmp/var/log 的 tmpfs 挂载点。

1.4 设置自动复制日志到 tmpfs

为了在系统启动时自动将日志复制到 tmpfs,我们需要修改 /etc/rc.local 文件:

a. 创建一个目录来存储持久化的日志:

sudo mkdir -p /var/log.hdd
sudo cp -a /var/log/* /var/log.hdd/

b. 编辑 /etc/rc.local 文件:

sudo nano /etc/rc.local

c. 在文件中添加以下内容:

#!/bin/sh -e
# 复制日志文件到 tmpfs
cp -a /var/log.hdd/* /var/log/
exit 0

d. 确保 rc.local 文件具有执行权限:

sudo chmod +x /etc/rc.local

2. 关闭 atime

atime (访问时间) 是文件系统的一个属性,每次访问文件时都会更新。关闭 atime 可以减少不必要的写入操作,从而延长 SD 卡的寿命。

如何关闭 atime

2.1 编辑 /etc/fstab 文件

打开 /etc/fstab 文件:

sudo nano /etc/fstab

2.2 修改挂载选项

找到 SD 卡对应的挂载项(通常是根分区 /),在挂载选项中添加 noatime:

UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx / ext4 defaults,noatime 0 1

2.3 重新挂载文件系统

保存文件后,使用以下命令重新挂载文件系统:

sudo mount -o remount /

请记住,虽然这些方法可以有效延长 SD 卡的使用寿命,但仍然建议定期备份重要数据,以防意外发生。毕竟备份不做,十恶不赦!

又:

mode=1777 中的 1 表示设置了"粘滞位"(sticky bit)。具体含义如下:

  1. 777 部分:

    • 7: 所有者(owner)有读、写、执行权限
    • 7: 用户组(group)有读、写、执行权限
    • 7: 其他用户(others)有读、写、执行权限
  2. 前面的 1:

    • 表示设置了粘滞位(sticky bit)

粘滞位的作用:

  • 对于目录,当设置了粘滞位时,只有文件的所有者、目录的所有者或 root 用户才能删除或重命名该目录中的文件。
  • 这通常用于像 /tmp 这样的公共目录,允许所有用户创建文件,但防止用户删除或修改其他用户的文件。

所以 mode=1777 的含义是:

  • 所有用户都可以在该目录中创建、读取和执行文件(777)
  • 但只有文件所有者和目录所有者可以删除或重命名文件(1)

这种权限设置既保证了目录的共享性,又提供了一定的安全保护,防止用户互相干扰。

How to Enable User-Level Systemd Services to Start Automatically on Ubuntu After Reboot

TL;DR

If your user-level systemd service on Ubuntu doesn't start automatically after a reboot, enable it with systemctl --user enable HappyNotes.Api.service. If you encounter an error about an existing symlink, remove it first. To allow the service to run without an active user session, enable lingering using loginctl enable-linger <username>. Finally, ensure your service file has the correct [Install] section and reboot to check if the service starts as expected.

The Problem

After configuring a user-level service with systemd, you might find that it remains inactive after rebooting your server. For example, you may run the command:

systemctl --user status HappyNotes.Api.service

And see output indicating that the service is inactive (dead) and disabled.

Solution Steps

  1. Enable the Service: First, ensure your service is enabled to start at boot:

    systemctl --user enable HappyNotes.Api.service
    

    If you encounter an error stating that the service is already linked, you may need to remove the existing symlink:

    rm ~/.config/systemd/user/default.target.wants/HappyNotes.Api.service
    
  2. Check for Linger: User-level services require an active user session to run. To allow your user services to run even when you're not logged in, enable lingering:

    loginctl enable-linger $USER
    
  3. Verify Service Configuration: Ensure your service file has the correct [Install] section:

    [Install]
    WantedBy=default.target
    
  4. Reboot and Test: After enabling lingering and ensuring your service is set up correctly, reboot your server:

    sudo reboot
    

    After rebooting, check the status of your service again:

    systemctl --user status HappyNotes.Api.service
    

By following these steps, you can ensure that your user-level systemd services start automatically after a reboot on Ubuntu. Enabling lingering is the key, which is particularly useful for server environments where continuous operation of services is desired.

Docker Volumes in Production: A Practical Guide to Named Volumes vs Bind Mounts

When working with Docker containers in production, understanding volume management is crucial. This guide will help you make informed decisions about when to use named volumes versus bind mounts (directory mapping).

TL;DR

  • Use named volumes for persistent data (databases, application state)
  • Use bind mounts for config files and development
  • Combine both in production for optimal setup

Understanding the Basics

Named Volumes

volumes:
  - postgres_data:/var/lib/postgresql/data

Docker manages these volumes internally. Think of them as "black boxes" that Docker handles for you.

Bind Mounts (Directory Mapping)

volumes:
  - ./config:/etc/app/config

You manage these directories directly on your host machine.

When to Use What?

Use Named Volumes For:

  1. Database storage
  2. Application state
  3. Generated assets
  4. Any data that needs persistence but not direct access

Benefits:

  • Managed by Docker
  • Better performance
  • Automatic permissions handling
  • Easier backups
  • Portable across environments
  • Built-in volume management commands

Use Bind Mounts For:

  1. Configuration files
  2. Static files during development
  3. Source code in development
  4. Any files you need to edit from host

Benefits:

  • Direct access from host
  • Easy to edit
  • Version control friendly
  • Quick updates without container restart
  • Shareable across environments

Real-World Example

Here's a typical production setup combining both approaches:

version: '3'
services:
  db:
    image: postgres:15
    volumes:
      # Data persistence with named volume
      - postgres_data:/var/lib/postgresql/data
      # Configuration with bind mounts
      - ./config/postgres.conf:/etc/postgresql/postgresql.conf:ro

  nginx:
    image: nginx
    volumes:
      # Config files with bind mounts
      - ./config/nginx/nginx.conf:/etc/nginx/nginx.conf:ro
      - ./config/nginx/conf.d:/etc/nginx/conf.d:ro
      # Static files with bind mount
      - ./static:/usr/share/nginx/html:ro

  app:
    image: node:18
    volumes:
      # Application data with named volume
      - app_data:/app/data
      # Config with bind mount
      - ./config/app.json:/app/config/app.json:ro

volumes:
  postgres_data:
  app_data:

Migration Tips

Moving from Bind Mounts to Named Volumes

If you're currently using bind mounts for data and want to switch to named volumes:

# Create new volume
docker volume create myapp_data

# Copy data
docker run --rm \
  -v /old/path:/source:ro \
  -v myapp_data:/destination \
  ubuntu \
  bash -c "cp -av /source/. /destination/"

Best Practices

  1. Named Volumes

    • Always use for persistent data
    • Name them descriptively
    • Regular backups
    • Don't manipulate directly on host
  2. Bind Mounts

    • Use read-only (:ro) when possible
    • Keep configs in version control
    • Use relative paths for portability
    • Store in a config/ directory
  3. General

    • Document your volume strategy
    • Regular backups for both types
    • Monitor disk usage
    • Use clear naming conventions

Common Pitfalls to Avoid

  1. Using bind mounts for database storage
  2. Hardcoding absolute paths
  3. Not setting proper permissions
  4. Forgetting to backup named volumes
  5. Direct manipulation of named volume directories

Conclusion

The key to successful Docker volume management is using the right tool for the job:

  • Named volumes for data that needs persistence
  • Bind mounts for configs and development
  • Combine both for a robust production setup

Remember: When in doubt, prefer named volumes for data and bind mounts for configuration.