add post, fix profile err

This commit is contained in:
2025-08-09 11:23:05 +09:00
parent 55745ff051
commit c3cb3db680
5 changed files with 1880 additions and 10 deletions

View File

@@ -0,0 +1,181 @@
---
title: "archlinuxのinstall"
slug: "arch"
date: "2025-08-08"
tags: ["arch"]
draft: false
---
## 最小構成
```sh
# cgdisk /dev/sda
```
```sh
$ mkfs.vfat /dev/sda1
$ mkfs.ext4 /dev/sda2
$ mount /dev/sda2 /mnt
$ mount --mkdir /dev/sda1 /mnt/boot
$ pacstrap /mnt base base-devel linux linux-firmware linux-headers
$ arch-chroot /mnt
$ pacman -S dhcpcd grub os-prober efibootmgr
$ grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=grub
$ grub-mkconfig -o /boot/grub/grub.cfg
```
これだけで`exit;reboot`すると起動できます。
## networkの設定
```sh
$ pacman -S git vim tmux zsh openssh
```
次にnetworkです。ここでは`systemd-networkd`を使用します。`dhcpcd`を使ったほうが簡単ではあります。もし安定しないようなら`dhcpcd`を使用。
```sh
# systemctl enable dhcpcd
```
```sh
$ systemctl enable systemd-networkd
```
network deviceをeth0にします。
```sh
$ ip link
$ ln -s /dev/null /etc/udev/rules.d/80-net-setup-link.rules
```
```sh:/etc/systemd/network/eth.network
[Match]
Name=eth0
[Network]
Address=192.168.1.2/24
Gateway=192.168.1.1
DNS=192.168.1.1
```
```sh
$ systemctl enable systemd-resolved
```
## auto-login
次にauto-loginを設定していきます。ここでは`getty`を使用。`${USER}`のところを自分のusernameにしてください。
```sh
$ mkdir -p /etc/systemd/system/getty@tty1.service.d/
```
```sh:/etc/systemd/system/getty@tty1.service.d/override.conf
[Service]
ExecStart=
ExecStart=-/usr/bin/agetty --autologin ${USER} --noclear %I $TERM
```
```sh
$ systemctl daemon-reload
$ systemctl restart getty@tty1
```
## window-manager
`xorg`でdesktop(window-manager)を作ります。`i3`を使うことにしましょう。`xorg`は`wayland`に切り替えたほうがいいかも。
```sh
$ pacman -S xorg xorg-xinit i3 xterm
# 確認
$ startx
$ i3
```
```sh:~/.xinitrc
exec i3
```
```sh:~/.bash_profile
if [[ ! $DISPLAY && $XDG_VTNR -eq 1 ]]; then
exec startx
fi
```
## sshの使い方
```sh
$ systemctl enable sshd
$ cat /etc/ssh/sshd_config
Port 22119
PasswordAuthentication no
$ systemctl restart sshd
```
基本的にlanで使う場合はdefaultで問題ありませんが、wanで使う場合は変更します。とはいえ、lanでもport, passwordは変えておいたほうがいいでしょう。
次に接続側でkeyを作ってserverに登録します。
```sh
$ ssh-keygen -f ~/.ssh/archlinux
$ ssh-copy-id -i ~/.ssh/archlinux ${USER}@192.168.1.2 -p 22119
```
`ssh-copy-id`がない場合は以下のようにしましょう。
```sh
$ cat ~/.ssh/archlinux.pub | ssh -p 22119 ${USER}@192.168.1.2 'cat >> ~/.ssh/authorized_keys'
```
この設定で`ssh archlinux`コマンドで接続できます。
```sh:~/.ssh/config
Host archlinux
User syui
Hostname 192.168.1.2
Port 22119
IdentityFile ~/.ssh/archlinux
```
おそらく、これがarchlinuxを普通に使っていくうえでの最小構成かと思います。
serverだけならxorgなどは必要ありません。
## zshの使い方
```sh
$ sudo pacman -S git-zsh-completion powerline zsh-autocomplete zsh-autosuggestions zsh-completions zsh-history-substring-search zsh-syntax-highlighting
```
例えば、`ls -`と入力すると補完され、`C-n`, `C-p`で選択。
```sh:~/.zshrc
alias u="sudo pacman -Syu --noconfirm"
alias zs="vim ~/.zshrc"
alias zr="exec $SHELL && source ~/.zshrc"
source /usr/share/zsh/plugins/zsh-autocomplete/zsh-autocomplete.plugin.zsh
source /usr/share/zsh/plugins/zsh-autosuggestions/zsh-autosuggestions.zsh
source /usr/share/zsh/plugins/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh
source /usr/share/zsh/plugins/zsh-history-substring-search/zsh-history-substring-search.zsh
# source /usr/share/powerline/bindings/zsh/powerline.zsh
autoload -Uz compinit
compinit
fpath=(/usr/share/zsh/site-functions $fpath)
HISTSIZE=10000
SAVEHIST=10000
HISTFILE=~/.zsh_history
setopt SHARE_HISTORY
setopt HIST_IGNORE_DUPS
bindkey '^[[A' history-substring-search-up
bindkey '^[[B' history-substring-search-down
```
`powerline`は重いのでコメントしています。

File diff suppressed because it is too large Load Diff

View File

@@ -83,11 +83,14 @@ export const atproto = {
return await request(`${apiEndpoint}/xrpc/${ENDPOINTS.getProfile}?actor=${actor}`)
},
async getRecords(pds, repo, collection, limit = 10, cursor = null) {
async getRecords(pds, repo, collection, limit = 10, cursor = null, reverse = false) {
let url = `${pds}/xrpc/${ENDPOINTS.listRecords}?repo=${repo}&collection=${collection}&limit=${limit}`
if (cursor) {
url += `&cursor=${cursor}`
}
if (reverse) {
url += `&reverse=true`
}
const res = await request(url)
return {
records: res.records || [],
@@ -151,7 +154,7 @@ export const collections = {
const cached = dataCache.get(cacheKey)
if (cached) return cached
const data = await atproto.getRecords(pds, repo, `${collection}.chat.comment`, limit)
const data = await atproto.getRecords(pds, repo, `${collection}.chat.comment`, limit, null, true) // reverse=true for chronological order
// Extract records array for backward compatibility
const records = data.records || data
dataCache.set(cacheKey, records)
@@ -161,7 +164,7 @@ export const collections = {
async getChat(pds, repo, collection, limit = 10, cursor = null) {
// Don't use cache for pagination requests
if (cursor) {
const result = await atproto.getRecords(pds, repo, `${collection}.chat`, limit, cursor)
const result = await atproto.getRecords(pds, repo, `${collection}.chat`, limit, cursor, true) // reverse=true for chronological order
return result
}
@@ -172,7 +175,7 @@ export const collections = {
return Array.isArray(cached) ? { records: cached, cursor: null } : cached
}
const data = await atproto.getRecords(pds, repo, `${collection}.chat`, limit)
const data = await atproto.getRecords(pds, repo, `${collection}.chat`, limit, null, true) // reverse=true for chronological order
// Cache only the records array for backward compatibility
dataCache.set(cacheKey, data.records || data)
return data

View File

@@ -45,7 +45,10 @@ pub struct ProfileFetcher {
impl ProfileFetcher {
pub fn new() -> Self {
Self {
client: reqwest::Client::new(),
client: reqwest::Client::builder()
.timeout(std::time::Duration::from_secs(30))
.build()
.unwrap_or_else(|_| reqwest::Client::new()),
}
}
@@ -84,11 +87,15 @@ impl ProfileFetcher {
let response = self.client
.get(&url)
.query(&[("repo", handle)])
.timeout(std::time::Duration::from_secs(10))
.send()
.await?;
.await
.map_err(|e| anyhow::anyhow!("Request failed: {}", e))?;
if !response.status().is_success() {
return Err(anyhow::anyhow!("Failed to describe repo: {}", response.status()));
let status = response.status();
let error_text = response.text().await.unwrap_or_default();
return Err(anyhow::anyhow!("Failed to describe repo: {} - {}", status, error_text));
}
let repo_desc: RepoDescription = response.json().await?;
@@ -117,11 +124,15 @@ impl ProfileFetcher {
let response = self.client
.get(&url)
.query(&[("actor", did)])
.timeout(std::time::Duration::from_secs(10))
.send()
.await?;
.await
.map_err(|e| anyhow::anyhow!("Request failed: {}", e))?;
if !response.status().is_success() {
return Err(anyhow::anyhow!("Failed to get profile: {}", response.status()));
let status = response.status();
let error_text = response.text().await.unwrap_or_default();
return Err(anyhow::anyhow!("Failed to get profile: {} - {}", status, error_text));
}
let profile_data: Value = response.json().await?;

View File

@@ -1875,7 +1875,7 @@ async fn check_and_process_new_posts(
async fn get_existing_records(config: &AuthConfig, collection: &str) -> Result<Vec<serde_json::Value>> {
let client = reqwest::Client::new();
let url = format!("{}/xrpc/com.atproto.repo.listRecords?repo={}&collection={}&limit=100",
let url = format!("{}/xrpc/com.atproto.repo.listRecords?repo={}&collection={}&limit=100&reverse=true",
config.admin.pds,
urlencoding::encode(&config.admin.did),
urlencoding::encode(collection));