Compare commits
3 Commits
c3cb3db680
...
4ce7ea9bd8
Author | SHA1 | Date | |
---|---|---|---|
4ce7ea9bd8
|
|||
cb8b0582e9
|
|||
85494944ad
|
181
my-blog/content/posts/2025-08-08-arch.md
Normal file
181
my-blog/content/posts/2025-08-08-arch.md
Normal 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`は重いのでコメントしています。
|
1675
my-blog/content/posts/2025-08-09-9935c5b5.md
Normal file
1675
my-blog/content/posts/2025-08-09-9935c5b5.md
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,5 @@
|
||||
import React, { useState } from 'react'
|
||||
import { logger } from '../utils/logger.js'
|
||||
|
||||
export default function AuthButton({ user, onLogin, onLogout, loading }) {
|
||||
const [handleInput, setHandleInput] = useState('')
|
||||
@@ -12,7 +13,7 @@ export default function AuthButton({ user, onLogin, onLogout, loading }) {
|
||||
try {
|
||||
await onLogin(handleInput.trim())
|
||||
} catch (error) {
|
||||
console.error('Login failed:', error)
|
||||
logger.error('Login failed:', error)
|
||||
alert('ログインに失敗しました: ' + error.message)
|
||||
} finally {
|
||||
setIsLoading(false)
|
||||
|
@@ -1,6 +1,7 @@
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import Avatar, { AvatarWithCard, AvatarList } from './Avatar.jsx'
|
||||
import { getAvatar, batchFetchAvatars, prefetchAvatar } from '../utils/avatar.js'
|
||||
import { logger } from '../utils/logger.js'
|
||||
|
||||
/**
|
||||
* Test component to demonstrate avatar functionality
|
||||
@@ -63,7 +64,7 @@ export default function AvatarTest() {
|
||||
|
||||
setTestResults(results)
|
||||
} catch (error) {
|
||||
console.error('Test failed:', error)
|
||||
logger.error('Test failed:', error)
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
@@ -78,7 +79,7 @@ export default function AvatarTest() {
|
||||
batchResults: Object.fromEntries(avatarMap)
|
||||
}))
|
||||
} catch (error) {
|
||||
console.error('Batch test failed:', error)
|
||||
logger.error('Batch test failed:', error)
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
@@ -94,7 +95,7 @@ export default function AvatarTest() {
|
||||
prefetchResult: cachedAvatar
|
||||
}))
|
||||
} catch (error) {
|
||||
console.error('Prefetch test failed:', error)
|
||||
logger.error('Prefetch test failed:', error)
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
|
@@ -1,6 +1,7 @@
|
||||
import React, { useState } from 'react'
|
||||
import { atproto, collections } from '../api/atproto.js'
|
||||
import { env } from '../config/env.js'
|
||||
import { logger } from '../utils/logger.js'
|
||||
|
||||
const ProfileForm = ({ user, agent, apiConfig, onProfilePosted }) => {
|
||||
const [text, setText] = useState('')
|
||||
@@ -79,7 +80,7 @@ const ProfileForm = ({ user, agent, apiConfig, onProfilePosted }) => {
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
console.error('Failed to create profile:', err)
|
||||
logger.error('Failed to create profile:', err)
|
||||
setError(err.message || 'プロフィールの作成に失敗しました')
|
||||
} finally {
|
||||
setPosting(false)
|
||||
|
@@ -1,6 +1,7 @@
|
||||
import React, { useState } from 'react'
|
||||
import { atproto } from '../api/atproto.js'
|
||||
import { getPdsFromHandle, getApiConfig } from '../utils/pds.js'
|
||||
import { logger } from '../utils/logger.js'
|
||||
|
||||
export default function UserLookup() {
|
||||
const [handleInput, setHandleInput] = useState('')
|
||||
@@ -26,7 +27,7 @@ export default function UserLookup() {
|
||||
config: apiConfig
|
||||
})
|
||||
} catch (error) {
|
||||
console.error('User lookup failed:', error)
|
||||
logger.error('User lookup failed:', error)
|
||||
setUserInfo({ error: error.message })
|
||||
} finally {
|
||||
setLoading(false)
|
||||
|
@@ -1,5 +1,6 @@
|
||||
import { useState, useEffect } from 'react'
|
||||
import { OAuthService } from '../services/oauth.js'
|
||||
import { logger } from '../utils/logger.js'
|
||||
|
||||
const oauthService = new OAuthService()
|
||||
|
||||
@@ -21,7 +22,7 @@ export function useAuth() {
|
||||
|
||||
// If we're on callback page and authentication succeeded, notify parent
|
||||
if (window.location.pathname === '/oauth/callback') {
|
||||
console.log('OAuth callback completed, notifying parent window')
|
||||
logger.log('OAuth callback completed, notifying parent window')
|
||||
|
||||
// Get referrer or use stored return URL
|
||||
const returnUrl = sessionStorage.getItem('oauth_return_url') ||
|
||||
@@ -48,7 +49,7 @@ export function useAuth() {
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Auth initialization failed:', error)
|
||||
logger.error('Auth initialization failed:', error)
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
|
@@ -2,6 +2,7 @@ import { BrowserOAuthClient } from '@atproto/oauth-client-browser'
|
||||
import { Agent } from '@atproto/api'
|
||||
import { env } from '../config/env.js'
|
||||
import { isSyuIsHandle } from '../utils/pds.js'
|
||||
import { logger } from '../utils/logger.js'
|
||||
|
||||
export class OAuthService {
|
||||
constructor() {
|
||||
@@ -44,7 +45,7 @@ export class OAuthService {
|
||||
// Try to restore session
|
||||
return await this.restoreSession()
|
||||
} catch (error) {
|
||||
console.error('OAuth initialization failed:', error)
|
||||
logger.error('OAuth initialization failed:', error)
|
||||
this.initPromise = null
|
||||
throw error
|
||||
}
|
||||
@@ -89,18 +90,18 @@ export class OAuthService {
|
||||
displayName = profile.data.displayName || null
|
||||
avatar = profile.data.avatar || null
|
||||
|
||||
console.log('Profile fetched from session:', {
|
||||
logger.log('Profile fetched from session:', {
|
||||
did,
|
||||
handle,
|
||||
displayName,
|
||||
avatar: avatar ? 'present' : 'none'
|
||||
})
|
||||
} catch (error) {
|
||||
console.log('Failed to get profile from session:', error)
|
||||
logger.log('Failed to get profile from session:', error)
|
||||
// Keep the basic info we have
|
||||
}
|
||||
} else if (did && did.includes('test-')) {
|
||||
console.log('Skipping profile fetch for test DID:', did)
|
||||
logger.log('Skipping profile fetch for test DID:', did)
|
||||
}
|
||||
|
||||
this.sessionInfo = {
|
||||
@@ -140,7 +141,7 @@ export class OAuthService {
|
||||
}
|
||||
return null
|
||||
} catch (error) {
|
||||
console.error('Auth check failed:', error)
|
||||
logger.error('Auth check failed:', error)
|
||||
return null
|
||||
}
|
||||
}
|
||||
@@ -168,7 +169,7 @@ export class OAuthService {
|
||||
// Reload page
|
||||
window.location.reload()
|
||||
} catch (error) {
|
||||
console.error('Logout failed:', error)
|
||||
logger.error('Logout failed:', error)
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -21,21 +21,14 @@ export default function AtUriViewer({ uri, onAtUriClick }) {
|
||||
setError(null)
|
||||
|
||||
try {
|
||||
console.log('Loading AT URI:', uri)
|
||||
const atUri = parseAtUri(uri)
|
||||
if (!atUri) {
|
||||
throw new Error('Invalid AT URI')
|
||||
}
|
||||
|
||||
console.log('Parsed AT URI:', {
|
||||
hostname: atUri.hostname,
|
||||
collection: atUri.collection,
|
||||
rkey: atUri.rkey
|
||||
})
|
||||
|
||||
const result = await getRecord(atUri.hostname, atUri.collection, atUri.rkey)
|
||||
|
||||
console.log('getRecord result:', result)
|
||||
|
||||
if (!result.success) {
|
||||
throw new Error(result.error)
|
||||
@@ -43,7 +36,6 @@ export default function AtUriViewer({ uri, onAtUriClick }) {
|
||||
|
||||
setRecord(result.data)
|
||||
} catch (err) {
|
||||
console.error('AtUriViewer error:', err)
|
||||
setError(err.message)
|
||||
} finally {
|
||||
setLoading(false)
|
||||
|
@@ -39,7 +39,6 @@ export const resolveIdentity = async (identifier) => {
|
||||
did = response.data.did
|
||||
resolved = true
|
||||
} catch (error) {
|
||||
console.log('Failed to resolve from syu.is:', error)
|
||||
}
|
||||
|
||||
if (!resolved) {
|
||||
@@ -64,7 +63,6 @@ export const resolveIdentity = async (identifier) => {
|
||||
didDoc = await plcResponse.json()
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('Failed to resolve from plc.syu.is:', error)
|
||||
}
|
||||
|
||||
// If plc.syu.is fails, try plc.directory
|
||||
@@ -75,7 +73,6 @@ export const resolveIdentity = async (identifier) => {
|
||||
didDoc = await plcResponse.json()
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('Failed to resolve from plc.directory:', error)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,17 +111,13 @@ export const resolveIdentity = async (identifier) => {
|
||||
// Get record from AT Protocol
|
||||
export const getRecord = async (did, collection, rkey) => {
|
||||
try {
|
||||
console.log('getRecord called with:', { did, collection, rkey })
|
||||
|
||||
const identityResult = await resolveIdentity(did)
|
||||
console.log('resolveIdentity result:', identityResult)
|
||||
|
||||
if (!identityResult.success) {
|
||||
return { success: false, error: identityResult.error }
|
||||
}
|
||||
|
||||
const pdsUrl = identityResult.pdsUrl
|
||||
console.log('Using PDS URL:', pdsUrl)
|
||||
|
||||
const client = createAtpClient(pdsUrl)
|
||||
|
||||
@@ -134,15 +127,12 @@ export const getRecord = async (did, collection, rkey) => {
|
||||
rkey
|
||||
})
|
||||
|
||||
console.log('getRecord response:', response)
|
||||
|
||||
return {
|
||||
success: true,
|
||||
data: response.data,
|
||||
pdsUrl
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('getRecord error:', error)
|
||||
return {
|
||||
success: false,
|
||||
error: error.message
|
||||
|
@@ -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?;
|
||||
|
Reference in New Issue
Block a user