DuetG Blog

Keep It Simple, Stupid

  • 在ARM开发板上自托管Bitwarden

    在ARM开发板上自托管Bitwarden

    结论:如果经济条件允许且对数据托管于别处不敏感,请首先选择1Password,除了数据托管在云上之外,使用体验是最好的。但要是对经济性有要求的话,建议使用完全免费的Vaultwarden。

    背景介绍:
    在Lastpass一再发生风险事故后,我决定将密码的管理迁移到1Password。但1Password较高的年费让我又产生了动摇。使用一年后,我决定再寻找一款合适自己的产品。对比过Enpass、KeePass等产品后,基础账号免费、具备多平台客户端且整个系统能够自托管的Bitwarden成为了我的选择。本文简明介绍在ARM开发板上部署Bitwarden服务的步骤。

    技术要求:
    本文需要有一定Docker以及Linux的使用经验,并假定使用root登录Debian/Ubuntu。另需要一条具备公网IP的宽带、一个域名以及一块ARM开发板。

    Bitwarden官方主流安装方法虽然也是在Docker下运行,但镜像并不支持ARM架构。如果是想在ARM开发板上运行Bitwarden,需要使用官方提供的Unified镜像,也就是集成化镜像。通过单一镜像可以大幅降低对系统资源的要求(最少200MB内存,1GB储存空间),理论上非ARM架构主板也能运行Unified镜像,但由于此安装方式目前仍在Beta阶段,官方支持度也只能说一般,大多数遇到的问题还得要自己研究解决。在部署过程中遇到的坑后面文章中会给出解决方法。

    准备SSL证书

    作为密码管理软件,在客户端和服务器端通信的过程如果是明文,会大大降低使用的安全性。Bitwarden需要有SSL连接(即https访问),则首先要在系统内准备SSL证书。虽然Docker镜像内也可以部署SSL证书(可通过Volume参数映射到容器外),但官方建议尽量在容器外使用Nginx配置证书,并通过反向代理将https的端口指向容器开放的非加密访问端口(如80)。可以申请使用免费证书,如Let’s Encrypt。

    安装Nginx

    apt update
    apt install nginx

    如果ARM开发板不能通过80端口来访问(国内家庭宽带绝大多数80、443、8080、8443都是被封锁的),而一般申请证书时要用80端口来验证。则需要使用DNS API来申请证书,这样就绕过了通过80端口验证的环节。Let’s Encrypt主推的Certbot是不具备这个验证功能的,这里我们使用acme.sh

    安装acme.sh

    #将[email protected]换成你自己的邮箱,如果没有curl的话先安装curl
    curl https://get.acme.sh | sh -s [email protected]

    安装过程中会有红色字样提示先安装socat,由于我们使用DNS API来申请证书,所以可以不用安装socat。acme.sh安装完成后重新登入一次账号,就可以直接使用acme.sh命令了。接下来我们通过域名托管的DNS服务来申请证书,acme.sh支持大量的DNS服务,我们以Cloudflare来举例。

    先在Cloudflare的个人资料页面左侧选择API令牌,然后再下一个页面点击右侧蓝色的创建令牌按钮。在API令牌模板中选择编辑区域DNS模板会大幅减少你的工作量。点击蓝色使用模板按钮后,在创建令牌中区域资源段最右侧的下拉菜单里选择你先前绑定在Cloudflare上的域名,随后点击下方蓝色的继续以显示摘要按钮,可以看到类似如下的令牌摘要:

    编辑区域 DNS API 令牌摘要

    此 API 令牌将影响以下帐户和区域,以及它们各自的权限

    确认无误后点击蓝色的创建令牌按钮,并在下个页面把虚线框中的字符串完整复制到桌面的文本文件里,这个就是你域名的DNS API令牌。接下来回到Cloudflare的账户主页,点击绑定的域名进入域名概述页面,在页面右侧下方找到区域ID和账户ID也复制到本地。接下来在ARM开发板的命令行中通过如下命令申请证书。

    #先导入令牌和账户ID以及区域ID
    export CF_Token="<token>"
    export CF_Account_ID="<id>"
    export CF_Zone_ID="<zone>"
    
    #再使用命令申请证书
    acme.sh --issue --dns dns_cf -d example.com

    证书申请成功后需要安装才可以使用,这里我们就借用Nginx内置的snakeoil文件所包含的证书位置和名称来安装证书。

    acme.sh --install-cert -d example.com \
    --key-file       /etc/ssl/private/ssl-cert-snakeoil.key  \
    --fullchain-file /etc/ssl/certs/ssl-cert-snakeoil.pem \
    --reloadcmd     "service nginx force-reload"

    证书完成安装后,开始写Nginx的配置文件

    #系统中如果没有vim的话可以先安装vim
    apt install vim
    #编辑Nginx默认配置文件
    vim /etc/nginx/sites-available/default

    请参考以下内容修改default文件,完成后按 :wq 保存并退出

    server {
            listen 443 ssl default_server;
            listen [::]:443 ssl ipv6only=on default_server;
     
            include snippets/snakeoil.conf;
    
            ssl_session_cache shared:le_nginx_SSL:10m;
            ssl_session_timeout 1440m;
            ssl_session_tickets off;
    
            ssl_protocols TLSv1.2 TLSv1.3;
            ssl_prefer_server_ciphers off;
    
            ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384";
    
            server_name _;
    
            location / {
                    ### Force timeouts if one of backend hosts is dead ###
                    proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
    
                    ### Set headers ###
                    proxy_set_header          X-Real-IP $remote_addr;
                    proxy_set_header          Accept-Encoding "";
                    proxy_set_header          Host $http_host;
                    proxy_set_header          X-Forwarded-For $proxy_add_x_forwarded_for;
    
                    ### Don't timeout waiting for long queries - timeout is 1 hr ###
                    proxy_read_timeout        3600;
                    proxy_set_header          X-Forwarded-Proto $scheme;
    
                    ### By default we don't want to redirect ###
                    proxy_redirect            off;
                   
                    ### Add Websocket proxy support ###
                    proxy_http_version 1.1;
                    proxy_set_header Upgrade $http_upgrade;
                    proxy_set_header Connection "upgrade";
    
                    proxy_pass http://127.0.0.1:80;
            }
    }

    保存并退出后使用以下命令重启Nginx

    service nginx force-reload

    以上是证书及Nginx反向代理的设置步骤。接下来开始为Bitwarden容器的运行做准备。首先是安装Docker,我们使用Docker官方的安装脚本来安装。

    #首先回到Home文件夹
    cd ~
    #下载安装脚本
    curl -fsSL https://get.docker.com -o install-docker.sh
    #浏览并测试脚本(也可以跳过)
    cat install-docker.sh
    sh install-docker.sh --dry-run
    #执行脚本安装Docker,如果从官方服务器下载速度很差,可以使用阿里云的镜像,安装操作请务必在root权限下进行
    sh install-docker.sh --mirror Aliyun

    安装完成后在Home中生成Bitwarden工作文件夹并进入并添加docker-compose.yml文件

    cd ~
    mkdir bitwarden
    cd bitwarden
    vim docker-compose.yml

    将下面内容按实际编辑后粘贴进vim并用 :wq 保存退出

    version: "3.8"
    
    services:
      bitwarden:
        depends_on:
          - db
        env_file:
          - settings.env
        image: ${REGISTRY:-bitwarden}/self-host:${TAG:-beta}
        restart: always
        ports:
          - "80:8080"
      #   - "443:8443"
        volumes:
          - bitwarden:/etc/bitwarden
          - logs:/var/log/bitwarden
    
      # MariaDB Example
      db:
        environment:
          MARIADB_USER: "bitwarden"
          MARIADB_PASSWORD: "super_strong_password" #建议修改password
          MARIADB_DATABASE: "bitwarden_vault"
          MARIADB_RANDOM_ROOT_PASSWORD: "true"
        image: mariadb:10
        restart: always
        volumes:
          - data:/var/lib/mysql
    
    volumes:
      bitwarden:
      logs:
      data:

    接下来添加Bitwarden的设置文件

    vim settings.env

    将下列内容编辑后粘贴进vim并用 :wq 保存退出

    #####################
    # Required Settings #
    #####################
    
    # Server hostname
    BW_DOMAIN=example.com
    
    # Database
    # Available providers are sqlserver, postgresql, mysql/mariadb, or sqlite
    BW_DB_PROVIDER=mysql
    BW_DB_SERVER=db
    BW_DB_DATABASE=bitwarden_vault
    BW_DB_USERNAME=bitwarden
    BW_DB_PASSWORD=super_strong_password  #和docker-compose.yml中一致
    
    # Installation information
    # Get your ID and key from https://bitwarden.com/host/
    # 请到 https://bitwarden.com/host/ 中输入邮箱并提交后免费获取
    BW_INSTALLATION_ID=xxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
    BW_INSTALLATION_KEY=xxxxxxxxxxxxxxxxxxxx
    
    #####################
    # Optional Settings #
    #####################
    # Learn more here: https://bitwarden.com/help/environment-variables/
    
    # Container user ID/group ID
    #PUID=1000
    #PGID=1000
    
    # Webserver ports
    #BW_PORT_HTTP=8080
    #BW_PORT_HTTPS=8443
    
    # SSL
    #BW_ENABLE_SSL=true
    #BW_ENABLE_SSL_CA=true
    #BW_SSL_CERT=ssl.crt
    #BW_SSL_KEY=ssl.key
    #BW_SSL_CA_CERT=ca.crt
    
    # Services
    # Some services, namely for enterprise use cases, are disabled by default. Defaults shown below.
    BW_ENABLE_ADMIN=true
    BW_ENABLE_API=true
    BW_ENABLE_EVENTS=false
    BW_ENABLE_ICONS=true
    BW_ENABLE_IDENTITY=true
    BW_ENABLE_NOTIFICATIONS=true
    BW_ENABLE_SCIM=false
    BW_ENABLE_SSO=false
    
    #BW_ICONS_PROXY_TO_CLOUD=false
    
    # Mail
    # 使用Gmail的SMTP服务发信
    globalSettings__mail__replyToEmail=noreply@$BW_DOMAIN
    globalSettings__mail__smtp__host=smtp.gmail.com
    globalSettings__mail__smtp__port=587
    globalSettings__mail__smtp__ssl=false
    [email protected]   #你的Gmail地址
    globalSettings__mail__smtp__password=xxxxxxxxxxxxxxxx   #你的Google账户的应用专用密码
    
    # Yubikey
    #globalSettings__yubico__clientId=REPLACE
    #globalSettings__yubico__key=REPLACE
    
    # Other
    #globalSettings__disableUserRegistration=true    #如想禁止注册请取消本行开头的注释
    #globalSettings__hibpApiKey=REPLACE
    adminSettings__admins="[email protected]"         #使用你的邮箱作为管理员登录的凭据
    #globalSettings__baseServiceUri__vault=https://example.com:1234     #如果使用了非标准端口,请取消本行注释并将完整带端口号的地址填在后面
    #下方BW_REAL_IPS是反向代理过程中可能会影响到获取真实IP的内网IP地址,以及后半段的是Cloudflare的IP地址,请按实际情况进行修改
    BW_REAL_IPS=172.0.0.0/8,127.0.0.1,192.168.2.0/24,173.245.48.0/20,103.21.244.0/22,103.22.200.0/22,103.31.4.0/22,141.101.64.0/18,108.162.192.0/18,190.93.240.0/20,188.114.96.0/20,197.234.240.0/22,198.41.128.0/17,162.158.0.0/15,104.16.0.0/13,104.24.0.0/14,172.64.0.0/13,131.0.72.0/22,2400:cb00::/32,2606:4700::/32,2803:f800::/32,2405:b500::/32,2405:8100::/32,2a06:98c0::/29,2c0f:f248::/32

    录入完成并保存退出后就可以使用Docker Compose启动Bitwarden

    docker compose up -d

    稍等一会儿,在浏览器中访问 https://{ARM开发板IP} ,应该会先看到证书错误的提示,选择继续访问就可以看到Bitwarden的登录页面。

    如果有公网IP的话,在路由器上利用DDNS服务把公网IP更新到域名A记录上,再用端口映射功能将ARM开发板内网IP的443端口映射到路由器上Bitwarden设置文件里自定义的端口(本例是1234)上,就可以直接用域名加端口号来访问Bitwarden了。在上方的例子中是 https://example.com:1234

    至此Bitwarden在ARM开发板的自托管便设置完成了。但是作为一款密码管理软件,如果不能备份数据库的话,使用风险是很高的。在Bitwarden Unified镜像的官方反馈帖中,官方明确表述了鉴于是自托管运行,所以目前不提供任何备份数据的功能,需要靠自己来完成备份。于是我们需要编写一个脚本,让机器定时完成备份。

    首先我们进入Bitwarden的工作文档新建一个备份文件夹,再新建一个备份脚本

    cd ~/bitwarden
    mkdir backups
    vim backup.sh

    将以下代码按实际情况修改后粘贴进 vim 并用 :wq 保存并退出

    #!/bin/bash
    # Backup database.
    
    docker exec bitwarden-db-1 sh -c 'exec mysqldump --all-databases -ubitwarden "super_strong_password"' > /root/bitwarden/backups/backup.sql
    #将上行命令中的密码修改为之前设置的密码
    
    now=$(date +"%Y-%m-%d-%H_%M")
    new_name=db_backup-${now}
    
    echo "Prepare backup folder from backup.sql and docker volume bitwarden_bitwarden"
    mkdir -p /root/bitwarden/backups/${new_name}
    mv /root/bitwarden/backups/backup.sql /root/bitwarden/backups/${new_name}/backup.sql
    cp -a /var/lib/docker/volumes/bitwarden_bitwarden /root/bitwarden/backups/${new_name}/
    cp -a /root/bitwarden/backup.sh /root/bitwarden/backups/${new_name}/
    cp -a /root/bitwarden/docker-compose.yml /root/bitwarden/backups/${new_name}/
    cp -a /root/bitwarden/restore.sh /root/bitwarden/backups/${new_name}/
    cp -a /root/bitwarden/settings.env /root/bitwarden/backups/${new_name}/
    
    echo "Compressing ${new_name} folder"
    tar -zcpf /root/bitwarden/backups/${new_name}.tar.gz -C /root/bitwarden/backups/${new_name} .
    rm -r /root/bitwarden/backups/${new_name}
    cd /root/bitwarden/backups/
    ls -t | sed -n '151,$p' | xargs -I {} rm -rf {}

    备份脚本会将所有和Bitwarden相关的数据全部备份并打包,以备份时间为文件名将压缩包保存在Bitwarden工作目录下的 backups 文件夹中。如果有支持 samba 协议的网络存储设备(如群晖NAS),还可以通过 smbclient 命令将备份的压缩包传送到别处异地备份。另外脚本最后一行命令确保备份文件夹中始终保持最新的150个备份,这个数字可以按需求自行调整。这里给一下 smbclient 的使用方法,可以添加到备份脚本的末尾。如果备份到群晖等NAS上,还可以使用类似Hyper Backup之类的程序继续将其备份到网络存储,但注意文件安全。

    smbclient -N //{NAS的IP}/home -U {NAS用户名}%{NAS密码} -t 120 -c 'cd /BitwardenBackup/; put /root/bitwarden/backups/'${new_name}'.tar.gz '${new_name}'.tar.gz'

    通过系统 cron 定期执行备份脚本,以达到自动备份的效果

    #编辑crontab
    crontab -e
    #将下行代码粘贴至crontab最后一行并保存退出,即可每6小时执行一次脚本
    0 */6 * * * sh /root/bitwarden/backup.sh > /dev/null

    如果重新部署Bitwarden需要还原数据可以用以下代码

    #!/bin/bash
    # Restore database.
    
    echo "Extract files from archive file"
    mkdir -p /root/bitwarden/backups/temp
    tar -zxpf $1 -C /root/bitwarden/backups/temp
    
    echo "Restore database"
    docker exec -i bitwarden-db-1 sh -c 'exec mysql -ubitwarden "-super_strong_password"' < /root/bitwarden/backups/temp/backup.sql
    #将上行命令中的密码修改为之前设置的密码
    
    echo "Restore docker volume bitwarden_bitwarden"
    rm -rf /var/lib/docker/volumes/bitwarden_bitwarden
    cp -af /root/bitwarden/backups/temp/bitwarden_bitwarden /var/lib/docker/volumes/
    
    echo "Clean work folder"
    rm -rf /root/bitwarden/backups/temp
    
    echo "Stop the running container, please restart manually"
    cd /root/bitwarden
    docker compose down

    将上述代码修改后保存为 restore.sh。先按照本文初的方式部署并运行Bitwarden(包括工作目录及备份文件夹的设置),将备份文件和 restore.sh 一同放入工作目录,保持Bitwarden运行中,执行

    sh restore.sh db_backup-xxxx-xx-xx-xx_xx.tar.gz

    完成还原数据后再执行一次启动Bitwarden的命令即可

    docker compose up -d

    至此Bitwarden Unified的备份还原工作也完成。

    另,acme.sh目前默认的证书服务由ZeroSSL提供,如果还想使用Let’s Encrypt,请在申请证书前先用下方命令切换默认证书服务到Let’s Encrypt,再操作证书申请

    acme.sh --set-default-ca --server letsencrypt

    再另,本文所提方法适用于家庭宽带有公网IP的情形,如家庭宽带不具备公网IP条件,可以使用Cloudflare Tunnel来完成内网穿透,实现通过标准端口访问内网ARM开发板,具体方法之后会再写一篇blog详述。

    Update: Cloudflare Tunnel相关的内容请参见这里

  • 香橙派安装Home Assistant Supervised

    香橙派安装Home Assistant Supervised

    Home Assistant

    一款用于智能家居的自由开源软件,旨在成为智能家居设备的中央控制系统,专注于本地控制和隐私。通过使用Android和iOS的配套应用程序,或使用支持的虚拟助手(如Google Assistant或Amazon Alexa)通过语音命令,可以访问基于Web的用户界面。

    香橙派

    香橙派(Orange Pi)是深圳市迅龙软件有限公司旗下开源产品品牌,迅龙软件成立于2005年,是全球领先的开源硬件和开源软件服务商,致力于让极客、创客、电子爱好者享用到来自中国的优质、低价的科技产品,通过大规模的社会化协作去创建一个更加美好的信息化人类文明。

    自从买了HomePod mini,在还没收到货的时候就开始盘算着怎么让HomePod能和家里的小米设备联动起来,实现通过Siri来控制小米设备。一开始在网上找的了一种通过米家App生成Siri快捷指令从而控制小米设备的方法。仔细研究了一下,发现这个方式并不合适自己:不但需要对每一个设备的每一种操作逐一生成快捷指令并录音,更麻烦的是即便设置完成,使用的时候还需要手机和所有设备同处一个局域网下才可以。这已经和“独立通过HomePod来控制设备”这个初衷背道而驰了。细想一下,这个方案合适的人群应该是单身并且小米设备较少的用户,通过简单的添加就可以零成本实现联动。满足这样条件的可以自行搜索一下,这里就不多做介绍了。

    在Goolge以及微信上搜索“HomeKit 小米”关键字,最后发现少数派上介绍智能家居的文章实在不少,后来又在知乎上看到了篇文章,并在文章下面的评论里找到了另一篇用Android手机安装Home Assistant的指南。又在文章里找到了这篇《香橙派安装HomeAssistant-supervised》,总算是确定了使用Home Assistant Supervised作为中控的方案。

    由于Home Assistant在不断迭代更新(Core更新的速度很快),虽然当时照着上篇教程搭配少数派里的文章最终实现了联动,但体验较差,并且在使用两个月后突然就失效了。于是又做了研究,最终完美实现,促成了写这篇blog的动机。鉴于前面提到的那篇教程有些过时了,这里我就从头再写一遍吧。

    硬件要求

    • 香橙派 3 LTS + 电源(可在香橙派官网页脚给出的官方销售链接里购买)
    • 闪迪64G TF卡(感觉买64G比32G划算,实际32G也可以)
    • TF卡USB读卡器(写卡用)
    • 香橙派 3 LTS 保护壳(不一定要买散热套装,官方旗舰店的透明黑壳也是没问题的,可以加一对散热片)

    1. 为香橙派烧录 Debian 11 系统

    点击下载官方镜像,提取码:9d7v (百度云盘)

    如果可以访问Google Drive的话,也可以去英文官网给出的链接下载,不用注册且速度很好。

    根据Home Assistant Supervised官方安装指南,只能安装在Debian 11 Bullseye上 (Ubuntu也不行) 目前要求安装在Debian 12 Bookworm上,但香橙派官方只给香橙派3 LTS做了Debian 11系统,我们后面会有相应的解决方案。所以我们要下载的文件是:

    Orangepi3-lts_3.0.8_debian_bullseye_server_linux5.16.17.7z

    Windows平台上的烧录方法参见香橙派 3 LTS 用户手册中的(推荐使用balenaEtcher)

    2.4. 基于 Windows PC 将 Linux 镜像烧写到 TF 卡的方法

    点击下载官方用户手册,提取码:g4xe (百度云盘)

    2. 通过 SSH 连接香橙派

    1. Windows用户可以在Microsoft Store里安装Windows Terminal,或者使用PuTTY。
    2. 烧录好系统的TF卡插回香橙派,用网线连接路由器和香橙派,并通电启动香橙派。
    3. 在路由器中查看香橙派的IP地址。
    4. 在终端里输入
      ssh root@香橙派IP地址
      香橙派IP地址请换成实际地址
    5. 输入密码 orangepi

    3. 修改系统 CGroup 至 v1

    这是和上面那篇教程完全不同的地方,那篇并没有提及修改系统cgroup版本。之前参考着安装的时候,虽然在安装程序上会提及cgroup版本变更失败,但在使用过程中并没有弹出任何错误。不过这次重装完成后进入Home Assistant后台会立刻受到关于cgroup版本不支持的通知。所以还是在安装Home Assistant前先把系统搞好再说下一步吧。

    CGroup

    cgroups,其名称源自控制组群(英语:control groups)的简写,是Linux内核的一个功能,用来限制、控制与分离一个进程组的资源(如CPU、内存、磁盘输入输出等)。

    从 cgroup v2文档可以查到,自Debian 11 bullseye起,Debian的cgroup默认就是v2了。试着刷了一下Debian 10 buster查了查,果然还是v1。然而根据Home Assistant官网的信息,Home Assistant Supervised只能安装在cgroup v1的系统上,且只能是Debian 11 bullseye。这就意味着,无论如何都要将bullseye系统默认的v2修改成v1(我曾试过将buster升级到bullseye,cgroup妥妥自动从v1升级成了v2)。

    虽然在后续安装Home Assistant Supervised的环节,安装包会用自动脚本让cgroup从v2切回v1,但这个操作仅限于非arm版的Debian。因为普通的Debian使用的bootloader是GRUB,这个脚本也是针对GRUB设计的,并没有考虑其他bootloader。而香橙派运行的是arm版的Debian,bootloader是U-Boot。这导致安装包的自动脚本会报错,无法把cgroup切回v1,我们只能手工修改香橙派上的cgroup。

    首先在命令行运行下面命令来确定系统的cgroup版本

    stat -fc %T /sys/fs/cgroup/

    如果是cgroup v2,返回 cgroup2fs
    如果是cgroup v1,则返回 tmpfs

    接下来修改cgroup到v1:

    1. 输入 cd /boot ,进入 /boot 目录
    2. 输入 cp boot.cmd boot.cmd.bak ,备份 boot.cmd
    3. 输入 vi boot.cmd ,进入到编辑界面
    4. 无视最上面的“DO NOT EDIT THIS FILE”
    5. 找到第38行:
      if test "${docker_optimizations}" = "on"; then setenv bootargs "${bootargs} cgroup_enable=memory swapaccount=1"; fi
    6. 按 i 键键入insert编辑状态,在swapaccount=1后面加上空格并输入:
      systemd.unified_cgroup_hierarchy=0
      修改后的第38行如下:
      if test "${docker_optimizations}" = "on"; then setenv bootargs "${bootargs} cgroup_enable=memory swapaccount=1 systemd.unified_cgroup_hierarchy=0"; fi
    7. 按 esc 键退出insert编辑状态,输入 :wq 回车完成保存并退出(对 vi 操作不熟悉的可以在网上查一下教程)
    8. 在命令行输入以下指令并回车,生成新的 boot.scr
      mkimage -C none -A arm -T script -d /boot/boot.cmd /boot/boot.scr
    9. 输入 reboot ,重启香橙派

    重启完成后用SSH连接进入命令行,再次使用下方命令查看cgroup版本

    stat -fc %T /sys/fs/cgroup/

    不意外的话应该返回 tmpfs,cgroup版本修改完成。

    4. 更新系统现有软件

    输入 apt update,更新软件源
    再输入 apt full-upgrade,更新现有软件

    5. 使用以下代码安装依赖

    接下来的步骤基本上就是Home Assistant官方的安装步骤了。安装过程中会提示部分软件已经安装过了,可忽略相关提示。

    Update:2024.01.15

    感谢网友提醒,文章已随官方步骤做修改。如后续官方程序再次有变动,请以上方链接的官方步骤为准。

    apt install \
    apparmor \
    cifs-utils \
    curl \
    dbus \
    jq \
    libglib2.0-bin \
    lsb-release \
    network-manager \
    nfs-common \
    systemd-journal-remote \
    systemd-resolved \
    udisks2 \
    wget -y

    6. 使用以下代码安装Docker-CE

    $ curl -fsSL https://get.docker.com -o get-docker.sh
    $ sh get-docker.sh --mirror Aliyun

    7. 安装OS-Agent

    先在这里查询最新的OS Agent版本:
    https://github.com/home-assistant/os-agent/releases/latest

    接下来用 wget 命令下载我们需要的安装包,注意选择正确的架构,香橙派应当选择 aarch64,如os-agent_1.6.0_linux_aarch64.deb

    右键复制安装包的下载地址,粘贴至终端,完成下载使用命令如下:

    $ wget https://github.com/home-assistant/os-agent/releases/download/1.6.0/os-agent_1.6.0_linux_aarch64.deb

    注意将地址替换成最新的版本,完成下载后再用以下命令安装:

    $ dpkg -i os-agent_1.6.0_linux_aarch64.deb

    8. 安装Home Assistant Supervised

    之前教程里相关的其他操作目前都被集成到了新版的安装包脚本里,所以只需要下载最新的安装包就可以了。

    Update 2024.01.15
    注意:由于最新的 homeassistant-supervised.deb 要求的Debian系统已经升级到12 Bookworm了,在Debian 11上安装的过程中检查依赖会报错缺少 systemd-resolved 这个包,而这个包是Debian 12上才有的,我们需要在安装命令中使用 --ignore-depends=systemd-resolved 来忽略掉这个报错。

    命令如下:

    $ wget -O homeassistant-supervised.deb https://github.com/home-assistant/supervised-installer/releases/latest/download/homeassistant-supervised.deb
    $ dpkg -i --ignore-depends=systemd-resolved homeassistant-supervised.deb

    安装过程中会看到切换cgroup版本的脚本执行失败的提示,不用管它。

    紧接着会自动进入蓝色选择机器类型的界面,注意选择机器类型 qemuarm-64

    如果选错了类型可以执行 dpkg -P homeassistant-supervised,卸载后再重新安装。

    默认的 $DATA_SHARE 文件夹位置在 /usr/share/hassio,所有Home Assistant相关的文件都在这个文件夹里。

    如果想更换位置需要在安装的时候指定,安装命令如下:

    $ DATA_SHARE=/想要指定的homeassistant文件夹位置 dpkg -i --ignore-depends=systemd-resolved homeassistant-supervised.deb

    9. 确认安装

    执行 docker ps 来查看容器的状态,一般来说需要20分钟左右会完成所有镜像的拉取和执行。如果很长时间都没有任何容器在运行,很可能是 ghcr.io 这个网址不通。需要执行 ping ghcr.io 来是否确认连通。

    如果不通需要查询 ghcr.io 的IP地址,并修改主机的 hosts 文件。具体方法请自行搜索,不再赘述。

    10. 使用Home Assistant

    浏览器地址栏输入 http://香橙派IP:8123,即可访问Home Assistant的管理后台,如果显示需要等待,就再多等一会儿。安装彻底完成后会显示注册用户的界面。关于Home Assistant的用法可以在少数派里搜到很多,这里不再多说,主要提一下Home Assistant社区市场(HACS)的安装方法,和小米设备集成的推荐。

    • HACS相当于为Home Assistant提供了更多的功能扩展,官方称之为集成,而非加载项。
      安装方法:
      1. 前往加载项商店 (第一次打开My Home Assistant页面需要配置一下,在框内输入 http://香橙派IP:8123,并保存,之后可以自动跳转)
      2. 搜索 SSH,安装社区版的 SSH & Web Terminal(如果搜索 SSH 没有任何结果,需要在你的用户资料下开启高级模式)
      3. 在 SSH & Web Terminal 的配置页面,选项一栏中找到 password: "" 一行,在引号中设置一个SSH密码(密码随便)。在网络一栏中设置一个SSH端口(数字随便)
      4. 在信息页面开启在侧边栏显示,并点击下方的启动
      5. 刷新页面后在左侧侧边栏找到 Terminal,点击并开启终端
      6. 在终端内执行 HACS 下载脚本
      wget -O - https://get.hacs.xyz | bash -
      7. 完成下载后通过添加集成,搜索HACS,跟着步骤便可完成安装和配置。
    • 关于小米设备集成主要介绍一下好用的HACS小米集成。
      之前查看少数派的文章,都在推荐”Xiaomi MIoT“这款集成,GitHub仓库地址是:
      https://github.com/ha0y/xiaomi_miot_raw
      但实际使用体验感觉一般,代码目前最后一次更新是4月10号,也有7个月没更新过了。这次重装之后尝试了”Xiaomi Miot Auto“这款,仓库地址是:
      https://github.com/al-one/hass-xiaomi-miot
      目前最后一次更新是18天前,实际用下来感觉非常不错,是目前我主力使用的小米集成。

    全文完

    Last Update: 2024.01.15

  • 人生检录处

    人生检录处

    孔子说“四十而不惑”。好像人总是要活到一个整数的年龄才能够顺利的跳进下一个阶段。当然这句话的开头是“吾十有五而志于学“,虽然不是整十的年龄,但对于一个Teenager来说,十五可能也算个神圣的数字。于是在这样一个看上去糟糕透顶的时间里,我进入到了三十几岁的最后一年。对于“四十不惑”的起跑线来说,自己算是已经在检录处点过到了。

    可能确实是只有人到了四十岁才能不再困惑吧,至少尽管现在已经开始了人生第三十九个年头几个小时了,我还是十分迷惑,甚至有些不知所措。也许我还得再等364天才行吧。

    疫情已经是第三个年头,不知道什么时候才能真正地结束,像03年那样忽然就悄无声息地过去。到目前为止我仍悲观地认为,只要不能尽快发明特效药与特效疫苗,所有人或早或晚在某个时间将会不可避免地全部被感染,无论政府采用何种抗疫方针。尽管如此,尽管我其实对自己被感染的结果早已不再恐惧,但在心底深处,我仍希望疫情能够彻底过去。全面爆发,绝大部分人感染,这样的结局能够避免发生。不是为了我自己,只是单纯地为了家人。没错,有了家人之后人的个性确实和之前不一样了。

    疫情中的这几年对很多人来说可能是停滞的几年,而对我来讲状况已经发生了很大变化。简而言之,自己终于找到了归宿成家了。这应该是我最后全家两人一起过的生日了,下一个生日的时候,也就是从检录处终于抵达起跑线的时候,就是三个人一起过生日了。这是一件值得期待的事情,让我对四十岁多了一些期待,尽管三十几岁的最后一年就像上学时母亲给的压钱包底用的十元纸币一样,让我十分地舍不得。而花时间和花钱不一样的是,尽管你再舍不得,也无法把时间存下来,早晚都会在那一天,把这最后的365天全部挥霍殆尽,然后毅然又或迷惘地带着全家跳进到自己不惑之年。而从现在起,孩子会越来越多地占据了我的人生,直至死方休。

    对于尚未出生的孩子来说,想必眼下也是他的人生检录处。不知道属于他的未来是怎样的一场比赛——田赛、径赛,又或是象棋、篮球也未可知。更重要的是,这会是一场公平的比赛吗?很快就要迎来孩子的起点了。人们总说不要输在起点,而这唯一的办法只有靠平日的训练,这训练自然是我们做父母的基本功了。可在这样一个混乱的时代,做父母的即便要多努力,也还是需要一些好运气的。

    希望一切顺利。

  • Langsam, bitte

    Langsam, bitte

    眼看天气一天天变暖,于是决定把因为太冷而停掉的锻炼的习惯再捡起来。这次不同于去年,不再是玩儿票似的随便跑跑,而是认真地启用了各种健康Apps:Zepp、Zepp Life(小米运动)、Keep、MyFitnessPal和WaterMinder等等,树立了75公斤的Flag,坚持每天运动(跑步、跳绳等),严格控制和计算卡路里摄入,以期能在两三个月后拥有一个精力充沛的肉体。

    这阵仗可能是这辈子我头次这么认真对待减肥和健康了,即便是在20多年前练田径的时候也没有过。要说到缘由,除了三个月后要面对呱呱坠地的婴儿,妻妊娠期略高的血糖也让我不得不重视起家庭的饮食结构和运动情况——厨房杀手自然是做不得,吃饱就倒对自己更无异于谋财害命:不但自己早早一命呜呼,还要把钱都送给医院。

    然而开始跑步的时候,在Keep上遇到了一个有趣的事儿,也是促使我想坐下来记录这篇文章的原因。虽说自己从小就跑步,甚至可以说曾经就是靠跑步吃饭来着,但在决定用Keep记录跑步,头次打开“跑步”这个项目时,在程序内向导的“循循善诱”下,我还是按照指导由程序给自己安排了一套长达四周的跑步计划。这有点儿像当年教练出的训练计划。我还依稀地记得郭琪教练拿着体育组里那个破旧的小夹板,在一沓卷了角的稿纸上编写着每日训练计划——那就是我那时每天下午3个小时命运的安排。于是Keep也为我往后的四周时间里安排了每天一小时左右的命运。

    只是这第一天的计划实在是有些太过简单:按配速9-10分/公里的速度跑30分钟。于是用臂包把手机绑上(有些Old School了,看了看现在年轻人都拿在手上),又把Amazfit手表的跑步状态激活,一副全副武装的模样在400米跑道上跑了起来。

    可是跑起来之后才发现,原来这并不是一件容易的事。

    (更多…)
  • Imagine

    Imagine

    希望乌克兰人民能平安无事