53 Commits

Author SHA1 Message Date
ca831cec40 chore: update 2022-01-11 00:03:36 +09:00
2a2a39f4a7 chore: update 2021-11-09 17:14:39 +09:00
fac6f1c2f7 cleanup 2021-11-08 20:40:03 +09:00
6cb2442786 chore: fix typo 2021-10-27 22:42:12 +09:00
073368e311 chore: fix ci 2021-10-27 15:54:47 +09:00
6176227dfa chore: fix ci 2021-10-27 15:53:06 +09:00
d807a0407f update 2021-10-11 12:24:57 +09:00
4fc8f4c77b update article 2021-07-28 15:22:05 +09:00
1816f001a3 chore: update 2021-07-21 00:06:13 +09:00
0164e25b69 add production config 2021-06-20 13:11:53 +09:00
8b685bca52 chore: cache multiple stages 2021-06-14 02:24:52 +09:00
20cd435743 fix article 2021-06-11 15:15:02 +09:00
e7e72727ae simplify payment page 2021-06-11 15:14:58 +09:00
7b900d92b2 fix theme 2021-06-08 22:10:25 +09:00
fc40162d5e fix branch 2021-06-08 21:08:40 +09:00
2d10c0ca80 remove CNAME 2021-06-08 21:08:05 +09:00
35dd54ca45 new articles 2021-06-08 21:04:52 +09:00
40251a91ba fix workflow 2021-06-08 21:02:01 +09:00
4f6717ef32 remove pages support 2021-06-08 21:00:32 +09:00
8e1de3f1ec cache support 2021-06-08 20:57:25 +09:00
78d820858a add watchtower 2021-06-08 20:43:42 +09:00
996f07c1bf fix workflows 2021-06-08 19:22:18 +09:00
acf6719ad2 fix dockerfile 2021-06-08 17:30:30 +09:00
a7084414b6 update articles 2021-06-08 16:50:58 +09:00
8b0111450b add nginx 2021-06-08 16:50:52 +09:00
4e9aacfab8 update 2021-06-06 21:56:40 +09:00
02b0c290ae update payments 2021-05-17 22:10:29 +09:00
1d28855a12 update links 2021-05-17 21:50:44 +09:00
087a185136 update payments 2021-05-17 21:45:17 +09:00
dependabot-preview[bot]
d9ca754951 Upgrade to GitHub-native Dependabot 2021-05-10 16:29:33 +09:00
3bdacc82e6 chore: update article 2021-05-06 13:53:02 +09:00
97de2db989 chore: update config 2021-05-06 13:52:46 +09:00
42c316a1fa update articles 2021-05-01 02:19:10 +09:00
051caa7790 chore: fix typo 2021-03-16 01:29:11 +09:00
67f0d6c485 fix typo 2021-02-28 12:40:24 +09:00
803242dde8 update article 2021-02-26 00:02:08 +09:00
0e8270cfad fix: payment 2021-02-25 23:08:48 +09:00
0c5f705b27 fix: typo 2021-02-25 22:59:32 +09:00
66b6186296 fix: typo 2021-02-25 22:36:19 +09:00
fcd16cd8cf fix: wrong language 2021-02-18 16:54:01 +09:00
e9771f6b7e update feed 2021-02-16 15:11:29 +09:00
325f206d15 fix: header 2021-02-14 17:24:36 +09:00
1ace2f62ea fix: light theme 2021-02-14 16:16:49 +09:00
fc140b995c fix: caption 2021-02-14 16:10:29 +09:00
a66fc37c03 feat: new articles 2021-02-14 15:47:14 +09:00
c5db049494 fix: 404 page 2021-02-13 22:22:34 +09:00
2afd947660 docs: rename article slug 2021-02-13 22:17:45 +09:00
ac0d966308 ci: remove travis 2021-02-13 21:47:22 +09:00
af9fde3fa9 ci: use ubuntu-20.04 2021-02-13 21:38:53 +09:00
396b7e5683 ci: use sudo 2021-02-13 21:34:27 +09:00
eecd97a8d3 ci: install pandoc 2021-02-13 21:33:34 +09:00
cc1d8047ab docs: add draft 2021-02-13 21:18:12 +09:00
039bac5e09 feat: use hexo 2021-02-13 21:18:11 +09:00
193 changed files with 2880 additions and 2944 deletions

View File

@@ -1,2 +0,0 @@
node_modules
vendor

View File

@@ -1,31 +1,28 @@
--- ---
new_page_extension: md new_page_extension: md
auto_deploy: false auto_deploy: false
admin_path: '' admin_path: ""
webhook_url: webhook_url:
sections: sections:
- type: jekyll-posts - type: directory
path: source/_posts
label: Posts label: Posts
create: documents create: documents
templates: match: "**/*"
- blog-post
- type: directory - type: directory
path: _pages path: source/_pages
label: Pages label: Pages
create: documents create: documents
match: "**/*" match: "**/*"
upload_dir: _uploads upload_dir: source/uploads
public_path: "/uploads" public_path: "/uploads"
front_matter_path: '' front_matter_path: ""
use_front_matter_path: false use_front_matter_path: false
file_template: ":filename:" file_template: ":filename:"
build: build:
preview_env: preview_output_directory: public
- JEKYLL_ENV=staging install_dependencies_command: npm i
preview_output_directory: _site
install_dependencies_command: bundle install --path vendor/bundle
preview_docker_image: forestryio/ruby:2.6 preview_docker_image: forestryio/ruby:2.6
mount_path: "/srv" mount_path: "/srv"
working_dir: "/srv" working_dir: "/srv"
instant_preview_command: bundle exec jekyll serve --drafts --unpublished --future instant_preview_command: yarn server
--port 8080 --host 0.0.0.0 -d _site

17
.github/dependabot.yml vendored Normal file
View File

@@ -0,0 +1,17 @@
version: 2
updates:
- package-ecosystem: npm
directory: "/"
schedule:
interval: monthly
time: "20:00"
timezone: Asia/Tokyo
open-pull-requests-limit: 10
ignore:
- dependency-name: textlint
versions:
- 11.7.7
- 11.8.1
- dependency-name: textlint-rule-no-dropping-the-ra
versions:
- 2.0.0

45
.github/workflows/ci.yml vendored Normal file
View File

@@ -0,0 +1,45 @@
# https://hexo.io/docs/github-pages.html
# https://github.com/docker/build-push-action/blob/master/docs/advanced/cache.md#github-cache
name: ci
on:
push:
branches:
- master
jobs:
buildAndPush:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
# - name: Set up QEMU
# uses: docker/setup-qemu-action@v1
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Login to GitHub Container Registry
uses: docker/login-action@v1
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push
id: docker_build
uses: docker/build-push-action@v2
with:
context: .
push: true
tags: ghcr.io/uetchy/uechi.io:latest
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Image digest
run: echo ${{ steps.docker_build.outputs.digest }}
- name: Trigger Watchtower Update
run: |
curl -s -H "Authorization: Bearer ${{ secrets.WATCHTOWER_TOKEN }}" https://watchtower.uechi.dev/v1/update

12
.gitignore vendored
View File

@@ -1,9 +1,11 @@
/.vscode /.vscode
/_site
/.sass-cache /.sass-cache
/node_modules/ /node_modules/
/npm-debug.log /npm-debug.log
/.jekyll-metadata .DS_Store
/images/crushed Thumbs.db
/.bundle db.json
/vendor/bundle/ *.log
public/
.deploy*/
yarn.lock

2
.prettierignore Normal file
View File

@@ -0,0 +1,2 @@
scaffolds/*
*.ejs

View File

@@ -1,10 +1,8 @@
{ {
"rules": { "rules": {
"max-ten": true,
"no-start-duplicated-conjunction": { "no-start-duplicated-conjunction": {
"interval": 2 "interval": 2
}, },
"no-dropping-the-ra": true,
"common-misspellings": true, "common-misspellings": true,
"preset-japanese": { "preset-japanese": {
"sentence-length": false "sentence-length": false
@@ -12,9 +10,7 @@
}, },
"filters": { "filters": {
"whitelist": { "whitelist": {
"allow": [ "allow": ["/{%.+?%}/"]
"/{%.+?%}/"
]
} }
} }
} }

View File

@@ -1,6 +0,0 @@
language: node_js
node_js: stable
notifications:
email:
on_success: never
on_failure: change

1
CNAME
View File

@@ -1 +0,0 @@
uechi.io

19
Dockerfile Normal file
View File

@@ -0,0 +1,19 @@
FROM node:15 as build
# https://github.com/jgm/pandoc/releases
RUN curl -LO https://github.com/jgm/pandoc/releases/download/2.14.0.1/pandoc-2.14.0.1-1-amd64.deb
RUN dpkg -i pandoc-2.14.0.1-1-amd64.deb
WORKDIR /app
COPY package.json /app/
RUN yarn install
COPY themes /app/themes
COPY source /app/source
COPY _config.yml /app/
RUN yarn build
FROM nginx:stable-alpine as runtime
COPY nginx.conf /etc/nginx/nginx.conf
COPY --from=build /app/public /var/www/html/

View File

@@ -1,3 +0,0 @@
source 'https://rubygems.org'
gem 'github-pages', group: :jekyll_plugins # workaround https://github.com/github/pages-gem#usage

View File

@@ -1,258 +0,0 @@
GEM
remote: https://rubygems.org/
specs:
activesupport (6.0.3.3)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 0.7, < 2)
minitest (~> 5.1)
tzinfo (~> 1.1)
zeitwerk (~> 2.2, >= 2.2.2)
addressable (2.7.0)
public_suffix (>= 2.0.2, < 5.0)
coffee-script (2.4.1)
coffee-script-source
execjs
coffee-script-source (1.11.1)
colorator (1.1.0)
commonmarker (0.17.13)
ruby-enum (~> 0.5)
concurrent-ruby (1.1.7)
dnsruby (1.61.4)
simpleidn (~> 0.1)
em-websocket (0.5.2)
eventmachine (>= 0.12.9)
http_parser.rb (~> 0.6.0)
ethon (0.12.0)
ffi (>= 1.3.0)
eventmachine (1.2.7)
execjs (2.7.0)
faraday (1.0.1)
multipart-post (>= 1.2, < 3)
ffi (1.13.1)
forwardable-extended (2.6.0)
gemoji (3.0.1)
github-pages (207)
github-pages-health-check (= 1.16.1)
jekyll (= 3.9.0)
jekyll-avatar (= 0.7.0)
jekyll-coffeescript (= 1.1.1)
jekyll-commonmark-ghpages (= 0.1.6)
jekyll-default-layout (= 0.1.4)
jekyll-feed (= 0.13.0)
jekyll-gist (= 1.5.0)
jekyll-github-metadata (= 2.13.0)
jekyll-mentions (= 1.5.1)
jekyll-optional-front-matter (= 0.3.2)
jekyll-paginate (= 1.1.0)
jekyll-readme-index (= 0.3.0)
jekyll-redirect-from (= 0.15.0)
jekyll-relative-links (= 0.6.1)
jekyll-remote-theme (= 0.4.1)
jekyll-sass-converter (= 1.5.2)
jekyll-seo-tag (= 2.6.1)
jekyll-sitemap (= 1.4.0)
jekyll-swiss (= 1.0.0)
jekyll-theme-architect (= 0.1.1)
jekyll-theme-cayman (= 0.1.1)
jekyll-theme-dinky (= 0.1.1)
jekyll-theme-hacker (= 0.1.1)
jekyll-theme-leap-day (= 0.1.1)
jekyll-theme-merlot (= 0.1.1)
jekyll-theme-midnight (= 0.1.1)
jekyll-theme-minimal (= 0.1.1)
jekyll-theme-modernist (= 0.1.1)
jekyll-theme-primer (= 0.5.4)
jekyll-theme-slate (= 0.1.1)
jekyll-theme-tactile (= 0.1.1)
jekyll-theme-time-machine (= 0.1.1)
jekyll-titles-from-headings (= 0.5.3)
jemoji (= 0.11.1)
kramdown (= 2.3.0)
kramdown-parser-gfm (= 1.1.0)
liquid (= 4.0.3)
mercenary (~> 0.3)
minima (= 2.5.1)
nokogiri (>= 1.10.4, < 2.0)
rouge (= 3.19.0)
terminal-table (~> 1.4)
github-pages-health-check (1.16.1)
addressable (~> 2.3)
dnsruby (~> 1.60)
octokit (~> 4.0)
public_suffix (~> 3.0)
typhoeus (~> 1.3)
html-pipeline (2.14.0)
activesupport (>= 2)
nokogiri (>= 1.4)
http_parser.rb (0.6.0)
i18n (0.9.5)
concurrent-ruby (~> 1.0)
jekyll (3.9.0)
addressable (~> 2.4)
colorator (~> 1.0)
em-websocket (~> 0.5)
i18n (~> 0.7)
jekyll-sass-converter (~> 1.0)
jekyll-watch (~> 2.0)
kramdown (>= 1.17, < 3)
liquid (~> 4.0)
mercenary (~> 0.3.3)
pathutil (~> 0.9)
rouge (>= 1.7, < 4)
safe_yaml (~> 1.0)
jekyll-avatar (0.7.0)
jekyll (>= 3.0, < 5.0)
jekyll-coffeescript (1.1.1)
coffee-script (~> 2.2)
coffee-script-source (~> 1.11.1)
jekyll-commonmark (1.3.1)
commonmarker (~> 0.14)
jekyll (>= 3.7, < 5.0)
jekyll-commonmark-ghpages (0.1.6)
commonmarker (~> 0.17.6)
jekyll-commonmark (~> 1.2)
rouge (>= 2.0, < 4.0)
jekyll-default-layout (0.1.4)
jekyll (~> 3.0)
jekyll-feed (0.13.0)
jekyll (>= 3.7, < 5.0)
jekyll-gist (1.5.0)
octokit (~> 4.2)
jekyll-github-metadata (2.13.0)
jekyll (>= 3.4, < 5.0)
octokit (~> 4.0, != 4.4.0)
jekyll-mentions (1.5.1)
html-pipeline (~> 2.3)
jekyll (>= 3.7, < 5.0)
jekyll-optional-front-matter (0.3.2)
jekyll (>= 3.0, < 5.0)
jekyll-paginate (1.1.0)
jekyll-readme-index (0.3.0)
jekyll (>= 3.0, < 5.0)
jekyll-redirect-from (0.15.0)
jekyll (>= 3.3, < 5.0)
jekyll-relative-links (0.6.1)
jekyll (>= 3.3, < 5.0)
jekyll-remote-theme (0.4.1)
addressable (~> 2.0)
jekyll (>= 3.5, < 5.0)
rubyzip (>= 1.3.0)
jekyll-sass-converter (1.5.2)
sass (~> 3.4)
jekyll-seo-tag (2.6.1)
jekyll (>= 3.3, < 5.0)
jekyll-sitemap (1.4.0)
jekyll (>= 3.7, < 5.0)
jekyll-swiss (1.0.0)
jekyll-theme-architect (0.1.1)
jekyll (~> 3.5)
jekyll-seo-tag (~> 2.0)
jekyll-theme-cayman (0.1.1)
jekyll (~> 3.5)
jekyll-seo-tag (~> 2.0)
jekyll-theme-dinky (0.1.1)
jekyll (~> 3.5)
jekyll-seo-tag (~> 2.0)
jekyll-theme-hacker (0.1.1)
jekyll (~> 3.5)
jekyll-seo-tag (~> 2.0)
jekyll-theme-leap-day (0.1.1)
jekyll (~> 3.5)
jekyll-seo-tag (~> 2.0)
jekyll-theme-merlot (0.1.1)
jekyll (~> 3.5)
jekyll-seo-tag (~> 2.0)
jekyll-theme-midnight (0.1.1)
jekyll (~> 3.5)
jekyll-seo-tag (~> 2.0)
jekyll-theme-minimal (0.1.1)
jekyll (~> 3.5)
jekyll-seo-tag (~> 2.0)
jekyll-theme-modernist (0.1.1)
jekyll (~> 3.5)
jekyll-seo-tag (~> 2.0)
jekyll-theme-primer (0.5.4)
jekyll (> 3.5, < 5.0)
jekyll-github-metadata (~> 2.9)
jekyll-seo-tag (~> 2.0)
jekyll-theme-slate (0.1.1)
jekyll (~> 3.5)
jekyll-seo-tag (~> 2.0)
jekyll-theme-tactile (0.1.1)
jekyll (~> 3.5)
jekyll-seo-tag (~> 2.0)
jekyll-theme-time-machine (0.1.1)
jekyll (~> 3.5)
jekyll-seo-tag (~> 2.0)
jekyll-titles-from-headings (0.5.3)
jekyll (>= 3.3, < 5.0)
jekyll-watch (2.2.1)
listen (~> 3.0)
jemoji (0.11.1)
gemoji (~> 3.0)
html-pipeline (~> 2.2)
jekyll (>= 3.0, < 5.0)
kramdown (2.3.0)
rexml
kramdown-parser-gfm (1.1.0)
kramdown (~> 2.0)
liquid (4.0.3)
listen (3.2.1)
rb-fsevent (~> 0.10, >= 0.10.3)
rb-inotify (~> 0.9, >= 0.9.10)
mercenary (0.3.6)
mini_portile2 (2.4.0)
minima (2.5.1)
jekyll (>= 3.5, < 5.0)
jekyll-feed (~> 0.9)
jekyll-seo-tag (~> 2.1)
minitest (5.14.2)
multipart-post (2.1.1)
nokogiri (1.10.10)
mini_portile2 (~> 2.4.0)
octokit (4.18.0)
faraday (>= 0.9)
sawyer (~> 0.8.0, >= 0.5.3)
pathutil (0.16.2)
forwardable-extended (~> 2.6)
public_suffix (3.1.1)
rb-fsevent (0.10.4)
rb-inotify (0.10.1)
ffi (~> 1.0)
rexml (3.2.4)
rouge (3.19.0)
ruby-enum (0.8.0)
i18n
rubyzip (2.3.0)
safe_yaml (1.0.5)
sass (3.7.4)
sass-listen (~> 4.0.0)
sass-listen (4.0.0)
rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7)
sawyer (0.8.2)
addressable (>= 2.3.5)
faraday (> 0.8, < 2.0)
simpleidn (0.1.1)
unf (~> 0.1.4)
terminal-table (1.8.0)
unicode-display_width (~> 1.1, >= 1.1.1)
thread_safe (0.3.6)
typhoeus (1.4.0)
ethon (>= 0.9.0)
tzinfo (1.2.7)
thread_safe (~> 0.1)
unf (0.1.4)
unf_ext
unf_ext (0.0.7.7)
unicode-display_width (1.7.0)
zeitwerk (2.4.0)
PLATFORMS
ruby
DEPENDENCIES
github-pages
BUNDLED WITH
2.1.4

View File

@@ -1,6 +1,6 @@
The MIT License (MIT) The MIT License (MIT)
Copyright (c) 2019 Yasuaki Uechi (https://uechi.io) Copyright (c) 2021 Yasuaki Uechi (https://uechi.io)
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

8
Makefile Normal file
View File

@@ -0,0 +1,8 @@
build:
docker-compose build --pull
push:
docker-compose push
deploy: build
docker-compose -f docker-compose.production.yml up -d

View File

@@ -1,19 +1,12 @@
# uechi.io # uechi.io
[![Build Status](https://travis-ci.com/uetchy/uechi.io.svg?branch=master)](https://travis-ci.org/uetchy/uechi.io) [![Actions Status: pages](https://github.com/uetchy/uechi.io/workflows/Pages/badge.svg)](https://github.com/uetchy/uechi.io/actions?query=pages)
## Build ## Build
``` ```
docker-compose run web bundle install n 15
docker-compose up --build yarn build
```
## Test
```
npm install
npm test
``` ```
## Publish ## Publish

View File

@@ -1,47 +1,145 @@
--- # Hexo Configuration
## Docs: https://hexo.io/docs/configuration.html
## Source: https://github.com/hexojs/hexo/
# Site
title: uechi.io title: uechi.io
timezone: Asia/Tokyo subtitle: ""
collections: description: "Random posts from U"
posts: keywords:
title: Posts author: Yasuaki Uechi
output: true language: en
uploads: timezone: "Asia/Tokyo"
title: Uploads
output: true excerpt:
defaults: depth: 1
- scope:
path: ''
type: posts
values:
layout: post
permalink: "/blog/:title"
description: Random posts from @uetchy.
url: https://uechi.io
email: y@uechi.io
twitter:
username: uechz
github: github:
username: uetchy username: uetchy
logo: "/images/icon.png" twitter:
excerpt_separator: "#" username: uechz
google_analytics: UA-28919359-12
plugins: umami:
- jekyll-redirect-from host: analytics.uechi.io
- jekyll-sitemap id: 2739f9aa-b8d5-45fa-8972-07a5bbb87e8a
- jekyll-seo-tag
- jekyll-feed node_sass:
- jemoji outputStyle: nested
include: precision: 5
- _pages sourceComments: false
exclude:
- README.md # URL
- LICENSE ## If your site is put in a subdirectory, set url as 'http://example.com/child' and root as '/child/'
- CNAME url: https://uechi.io
- Gemfile root: /
- Gemfile.lock permalink: /blog/:name/
- package.json permalink_defaults:
- node_modules pretty_urls:
- script trailing_index: true # Set to false to remove trailing 'index.html' from permalinks
- vendor trailing_html: true # Set to false to remove trailing '.html' from permalinks
- docker-compose.yml
- Dockerfile # Directory
source_dir: source
public_dir: public
tag_dir: tags
archive_dir: archives
category_dir: categories
code_dir: downloads/code
i18n_dir: :lang
skip_render:
# Writing
new_post_name: :title.md # File name of new posts
default_layout: post
titlecase: false # Transform title into titlecase
external_link:
enable: true # Open external links in new tab
field: site # Apply to the whole site
exclude: ""
filename_case: 0
render_drafts: false
relative_link: false
future: true
post_asset_folder: true
marked:
prependRoot: true
postAsset: true
# Math
mathjax:
tags: none # or 'ams' or 'all'
single_dollars: true # enable single dollar signs as in-line math delimiters
cjk_width: 0.9 # relative CJK char width
normal_width: 0.6 # relative normal (monospace) width
append_css: true # add CSS to pages rendered by MathJax
every_page: true # if true, every page will be rendered by MathJax regardless the `mathjax` setting in Front-matter
# Highlight
highlight:
enable: true
line_number: false
auto_detect: false
tab_replace: ""
wrap: false
hljs: true
prismjs:
enable: false
# Home page setting
# path: Root path for your blogs index page. (default = '')
# per_page: Posts displayed per page. (0 = disable pagination)
# order_by: Posts order. (Order by date descending by default)
index_generator:
path: ""
per_page: 20
order_by: -date
# Category & Tag
default_category: uncategorized
category_map:
tag_map:
# Metadata elements
## https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meta
meta_generator: true
# Date / Time format
## Hexo uses Moment.js to parse and display date
## You can customize the date format as defined in
## http://momentjs.com/docs/#/displaying/format/
date_format: YYYY-MM-DD
time_format: HH:mm:ss
## updated_option supports 'mtime', 'date', 'empty'
updated_option: "mtime"
# Pagination
## Set per_page to 0 to disable pagination
per_page: 20
pagination_dir: page
# Include / Exclude file(s)
## include:/exclude: options only apply to the 'source/' folder
# include:
# exclude:
ignore:
# Extensions
## Plugins: https://hexo.io/plugins/
## Themes: https://hexo.io/themes/
theme: uio
# Feed
feed:
limit: 20
order_by: "-date"
tag_dir: "tag"
category_dir: "category"
rss:
enable: false
jsonFeed:
enable: true
output: "feed.json"
atom:
enable: true
output: "feed.xml"

View File

View File

View File

@@ -1,12 +0,0 @@
---
title: Deconvolutionと呼ぶのはもうやめよう
date: 2017-03-05 13:44:00 +09:00
---
深層学習において、Convolutional Layer (畳み込み層)とは、あるシェイプのテンソルをそれ以下のサイズに縮約する性質のレイヤーです。一方で Deconvolution Layer (逆畳み込み層)とは、[Jonathan Long, et al](https://arxiv.org/abs/1411.4038)の論文で提案されたレイヤーで、あるシェイプのテンソルをそれ以上のサイズに拡大する性質を持ちます。
ところが実際のところ、このレイヤーは Transposed Convolution Layer (転置畳み込み層)と呼ぶべきです。なぜかを以下に示します。
> Upsampling is backwards strided convolution. (アップサンプリングは
[Stack Exchange](http://datascience.stackexchange.com/questions/6107/what-are-deconvolutional-layers)での議論を踏まえると

View File

@@ -1,11 +0,0 @@
---
title: 'gst: a powerful pal for ghq'
date: 2017-06-02 23:02:00 +09:00
---
[gst](https://github.com/uetchy/gst) is tiny and simple but powerful pal for [ghq](https://github.com/motemen/ghq).
Have you ever imagined what if you know which commits are unpushed or which changes are uncommitted yet, for all of the repositories you have cloned on your machine?
You might want to check out my ongoing project `gst`:
it might help you to know what ongoing changes are remained to be committed or pushed among entire your local repositories.

View File

@@ -1,46 +0,0 @@
---
date: 2020-03-16 18:19:11 +0900
title: pixiv SPRING BOOT CAMP 2020
---
[pixiv SPRING BOOT CAMP 2020](https://www.pixiv.co.jp/news/recruit/article/8728/)に参加した。インターン自体が初めてということもあり、普段とは種類の異なる様々な知見を得ることができたので共有したい。
## 選考
選考は Google Hangout Meet を用いたオンラインセッションで実施された。質問内容は以下の通りである。
- 自己紹介
- コースの希望とその理由
- 簡単なコーディングテスト
フロントエンドを希望したため、コーディングテストは JavaScript を用いてフォーム画面を設計するという内容になっていた。
React を用いて MVP を実装し、それからインタビュワーのツッコミを打ち返すという形式であった。
選考結果は次の日に通知された。選考に関するフローは洗練されており、よく設計されているように感じた。
## オリエンテーション
- NDA
- ラジオ体操
- 自己紹介
## 業務
- iMac
- YubiKey
- 課題 1. psd.js の TypeScript 移植
- 課題 2. 通知 API の JSON API 化+React 化
- 同人誌入稿画面のレスポンシブ化
- 新しい入稿フローの提案
### ランチ
- タコライス
- LINE Pay
- PayPay
## 成果発表
## 感想
### 社風

View File

@@ -1,14 +0,0 @@
---
date: 2020-02-13 16:22:05 +0900
title: 静寂を得る方法
---
聴覚過敏であったり、そうでなくとも周りの音がパフォーマンスに悪影響となる人のために、静寂を得る方法を紹介します。
## EARIN M-2
[EARIN](https://earin.com/) は左右分離型Bluetoothイヤホンです。付属のイヤホンの代わりに自分の耳にフィットするComplyのイヤーチップと付け替えます。
## Moldex
Moldex は使い捨て耳栓のメーカーであり、各種遮音レベルに分かれた多様なラインナップを提供しています。

View File

@@ -1,25 +0,0 @@
<!-- Google Analytics -->
<script>
;(function(i, s, o, g, r, a, m) {
i['GoogleAnalyticsObject'] = r
;(i[r] =
i[r] ||
function() {
;(i[r].q = i[r].q || []).push(arguments)
}),
(i[r].l = 1 * new Date())
;(a = s.createElement(o)), (m = s.getElementsByTagName(o)[0])
a.async = 1
a.src = g
m.parentNode.insertBefore(a, m)
})(
window,
document,
'script',
'https://www.google-analytics.com/analytics.js',
'ga'
)
ga('create', '{{ site.google_analytics }}', 'auto')
ga('send', 'pageview')
</script>

View File

@@ -1,53 +0,0 @@
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="shortcut icon" href="{{ site.baseurl }}/images/favicon.ico" />
<link
rel="apple-touch-icon"
sizes="180x180"
href="{{ site.baseurl }}/images/apple-touch-icon.png"
/>
<link
rel="icon"
type="image/png"
href="{{ site.baseurl }}/images/favicon-32x32.png"
sizes="32x32"
/>
<link
rel="icon"
type="image/png"
href="{{ site.baseurl }}/images/favicon-16x16.png"
sizes="16x16"
/>
<link
rel="mask-icon"
href="{{ site.baseurl }}/images/safari-pinned-tab.svg"
color="#5bbad5"
/>
{% seo %} {% feed_meta %}
<!-- Normalize -->
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/normalize/7.0.0/normalize.min.css"
/>
<!-- Share -->
<script
defer
src="https://connect.facebook.net/en_US/sdk.js#xfbml=1&version=v2.8"
id="facebook-jssdk"
></script>
<script
defer
src="https://platform.twitter.com/widgets.js"
id="twitter-wjs"
></script>
<!-- Styles -->
<link rel="stylesheet" href="{{ site.baseurl }}/css/index.css" />
</head>

View File

@@ -1,9 +0,0 @@
---
layout: default
---
<section>
<article class="article">
<div class="article__content">{{ content }}</div>
</article>
</section>

View File

@@ -1,10 +0,0 @@
<!DOCTYPE html>
<html>
{% include head.html %}
<body>
{% include header.html %}
{{ content }}
{% include footer.html %}
</body>
</html>

View File

@@ -1,26 +0,0 @@
---
title: Page Not Found
permalink: "/404.html"
excerpt: ''
---
<!DOCTYPE html>
<html>
{% include head.html %}
<style>
h1 {
font-size: 12em;
font-weight: 100;
margin: 0;
}
</style>
<body>
{% include header.html %}
<section class='page-section error-page'>
<div class='container-narrow text-center py-md-8'>
<h1>404</h1>
<p class="lead">This page could not be found</p>
</div>
</section>
</body>
</html>

View File

@@ -1,53 +0,0 @@
---
permalink: "/"
layout:
---
<!DOCTYPE html>
<html>
{% include head.html %}
<body>
<div class="metro">
<h1 class="logo">
<img src="{{ site.baseurl }}/images/logo.svg" style="height: 50px" />
</h1>
<nav>
<ul class="menu">
<li class="menu__item">
<a href="/me">Me</a>
</li>
<li class="menu__item">
<a href="https://github.com/{{ site.github.username }}">GitHub</a>
</li>
<li class="menu__item">
<a href="https://twitter.com/{{ site.twitter.username }}"
>Twitter</a
>
</li>
<li class="menu__item">
<a href="/wallpaper">Wallpaper</a>
</li>
</ul>
</nav>
</div>
<section>
{% for post in site.posts %}
<article class="article-list__item">
<h2 class="article-list__item__title">
<a href="{{ post.url | prepend: site.baseurl }}">{{ post.title }}</a>
</h2>
<!-- <time class="article-list__item__pubdate" pubdate>{{ post.date | date: '%B %d, %Y' }}</time> -->
<article class="article-list__item__excerpt">
{{ post.excerpt | strip_html | truncate: 140, "..." }}
</article>
<a
class="article-list__item__button"
href="{{ post.url | prepend: site.baseurl }}"
>Read more</a
>
</article>
{% endfor %}
</section>
{% include footer.html %}
</body>
</html>

View File

@@ -1,48 +0,0 @@
---
title: Yasuaki Uechi
permalink: "/me"
layout: article
---
<style>
img {
width: auto !important;
}
</style>
# README
> I'm **Yasuaki Uechi**, a graduate student studying about recurrent neural networks. I was born in Okinawa, Japan in 1994 and have been living in Kanagawa.
# Contact
Reach me at `y@uechi.io` (recommended) or [@uechz](https://twitter.com/uechz) on Twitter. Beware that I'm not a person of quick reply so if you are in urgent need of a lightning response better bomb my inbox with reminders so I can prioritize your email than any other emails.
## GPG Key
Get [GPG Key](https://github.com/uetchy.gpg) on GitHub.
# Facts
- play violin, tin whistle, piano, and bodhrán. Logic Pro user.
- overall interests: ux/graphic design, webdev, machine learning (mainly nlp and generative design), behavioral economics, organization government, irish music, coffee, puzzle game
- dev interests: react, nodejs, rust, docker
- have confidence in: javascript (incl. nodejs and typescript), python, ux design, baremetal server, english
- have no confidence in: normal life stuff
- have some experience in: swift, go, ruby, rust, c++, pytorch
- language skills:
- Japanese: native
- English: TOEIC 940, TOEFL 78
- Chinese, Korean, Indonesian, German, Russian: current objectives still n00b though
- typeface fanatic
# Publishing
- [Open Source @ GitHub](https://github.com/uetchy)
- [Technical Note (English) @ dev.to](https://dev.to/uetchy)
- [Technical Note (Japanese) @ Qiita](https://qiita.com/uetchy)
- [Design Portfolio @ Behance](https://www.behance.net/uechi)
# Current Activity
- Seeking for a job

View File

@@ -1,60 +0,0 @@
---
title: Pay
permalink: "/pay"
layout: default
---
<div id="pay">
<section>
<p>
送金方法はオススメ順に並んでいます。いずれか都合の良い方法で送金または請求してください。
</p>
</section>
<section>
<h1>Kyash</h1>
<p>
QRコードをスキャンするか、Kyash ID
<span class="monospace">uechi</span> 宛に送金・請求してください。
</p>
<img src="/images/payment/kyash.png" width="200" height="200" />
<a class="button" href="kyash://qr/u/7175222723044580164">Kyashを開く</a>
<br />
</section>
<section>
<h1>LINE Pay</h1>
<p>LINE宛に送金・請求してください。</p>
<a class="button" href="https://line.me/ja/pay">LINE Payについて</a>
</section>
<section>
<h1>Revolut</h1>
<p><span class="monospace">yasuakpnqg</span> 宛にお送りください。</p>
<a class="button" href="https://pay.revolut.com/profile/yasuakpnqg"
>Revolutを開く</a
>
</section>
<section>
<h1>Amazon ギフトカード</h1>
<p>
メッセージアプリ経由で、または
<span class="monospace">y@uechi.io</span> 宛にお送りください。
</p>
<a class="button" href="https://www.amazon.co.jp/gp/product/B004N3APGO/"
>Amazonを開く</a
>
</section>
<section>
<h1>PayPay</h1>
<p>QRコードをスキャンして送金してください。</p>
<img src="/images/payment/paypay.png" width="200" height="200" />
<a class="button" href="https://paypay.ne.jp/">PayPayについて</a> <br />
</section>
<section>
<h1>PayPal</h1>
<p>
PayPalで
<span class="monospace">y@uechi.io</span> 宛に送金・請求してください。
</p>
<a class="button" href="https://paypal.me/uetchy">PayPalを開く</a>
<br />
</section>
</div>

View File

@@ -1,48 +0,0 @@
---
title: Wallpapers
permalink: "/wallpaper"
layout: post
---
Right-click and choose **Save Image** to download my wallpapers. All following pictures are my own work and are published on Creative Commons BY-NC-SA.
![Sunrise]({{ site.baseurl }}/images/wallpaper/sunrise.png)
![Black Matter]({{ site.baseurl }}/images/wallpaper/blackmatter.png)
![Rockstar]({{ site.baseurl }}/images/wallpaper/rockstar.png)
![Rock Mountain]({{ site.baseurl }}/images/wallpaper/rockmountain.png)
<div style="display: flex; flex-direction: row">
<div><img src="{{ site.baseurl }}/images/wallpaper/vertex.png" /></div>
<div style="margin-left: 20px"><img src="{{ site.baseurl }}/images/wallpaper/vertex2.png" /></div>
</div>
![Ridge]({{ site.baseurl }}/images/wallpaper/ridge.png)
![Starrysky Orange]({{ site.baseurl }}/images/wallpaper/starrysky-orange.png)
![Desert]({{ site.baseurl }}/images/wallpaper/desert.png)
![Bricks]({{ site.baseurl }}/images/wallpaper/bricks.png)
![Starry Sky]({{ site.baseurl }}/images/wallpaper/starrysky.png)
![Dawn]({{ site.baseurl }}/images/wallpaper/dawn.png)
![Path]({{ site.baseurl }}/images/wallpaper/path.png)
![Shrine]({{ site.baseurl }}/images/wallpaper/shrine.png)
## Monochrome
![Ridge Monochrome]({{ site.baseurl }}/images/wallpaper/ridge-mono.png)
![Ridge Monochrome 2]({{ site.baseurl }}/images/wallpaper/ridge-mono2.png)
![Desert Monochrome]({{ site.baseurl }}/images/wallpaper/desert-mono.png)
![Bricks Monochrome]({{ site.baseurl }}/images/wallpaper/bricks-mono.png)
![Shrine Monochrome]({{ site.baseurl }}/images/wallpaper/shrine-mono.png)

View File

@@ -1,83 +0,0 @@
---
title: 生活の自動化
date: 2018-08-05 00:00:00 +09:00
redirect_from: "/blog/2018/08/05/life-automation"
---
生活にオートメーションを上手く取り入れ、本当にやりたいことや、やるべきことに集中できる環境をつくろう。
# 洗濯の自動化
Panasonic のドラム洗濯乾燥機を使っている。威力を最大限に享受するため、タンブラー乾燥向けの普段着を揃えておくことも重要だ。
洗剤は粉と液体とが一体化したジェルボール洗剤が便利。ドラムの底にひとつ置くだけでよく、計量する必要がない。
# 食器洗いの自動化
Panasonic NC-TCR2 という一人暮らし用のコンパクト食洗乾燥機が便利。
洗濯機と同じく食洗機専用のジェルボール洗剤を使えば計量する手間を省ける。
# 照明の自動化
Hue はインターネット経由で明るさや色相をコントロールすることができる電球である。
- 「家から離れたら消灯」
- 「家に近付いたら点灯」
- 「日が暮れたら暖色系に切り替える」
- 「23 時になったら消灯」
など多様なルールを作ることができる。
家では外の明るさに合わせて照明の明るさを調整して、概日リズムが崩れにくいようにルールを決めている。
# 空調の自動化
Nature Remo でエアコンの操作を自動化した。
- 「湿度が高ければドライに変更」
- 「家から離れたら電源オフ」
- 「朝になったら冷房へ切り替え」
など多様なルールを作ることができる。
Nature Remo 自体はエアコン専用ではなく、赤外線で操作出来るデバイスであればなんでも操作できる。家ではテレビもこれで操作している。
ちなみに[Nature Remo を NodeJS で操作することができるライブラリ](https://github.com/uetchy/nature-remo)を作ったので、是非使ってみて欲しい。ライブラリ経由で温度・湿度・明度のセンサー値を取得したり、指定したモードにエアコンを切り替えることができる。
# 自動施錠・自動開錠
Qrio Lock をドアに取り付けることでオートロックとオートアンロックができるようになった。
# 睡眠記録の自動化
Withings 改め Nokia の Sleep を使っている。
睡眠を計測する際、身体にウェアラブルデバイスを身につける必要がないという点で、Nokia Sleep は Apple Watch や Fitbit よりも優れている。
機能としては、入眠・起床検知、心拍数記録、睡眠深度解析、いびき検出、IFTTT 連携がある。
# 体重記録の自動化
Withings の Wi-Fi Scale を使っている。体重と体脂肪率、心拍数、BMI を Wi-Fi 経由でクラウドに自動記録し、Apple Health などで推移を確認できる。
Wi-Fi Scale には CO2 センサーもついており、部屋の二酸化炭素濃度を記録してくれる。
# コーヒー豆のサブスクリプション
珈琲きゃろっとのサブスクリプションを利用している。
# オンラインスーパー
イトーヨーカドーのオンラインスーパーを使っている。お気に入りリストへ牛乳、オレンジ、ベーコン、卵など毎回買うものを登録しておくことで、慣れれば 5 分程度で注文が完了する。あとは指定した時間に家へ商品を届けてくれる。
# 自動家計簿
MoneyForward を使っている。支出を自動で食費、趣味、日用品などに仕分けてくれる。
無現金縛りプレイと相性が良い。
# 自炊の効率化
最近 COMP で食事を置き換え始めた。まだ評価は出来ないが少なくとも味は悪くなく(薄いきな粉のような味)、不足しがちなビタミンや鉄分を補える点では良い製品だと思う。
# 気になる製品
## ルンバ
ルンバは気になるが、絨毯を取り除くわけにもいかないので二の足を踏んでいる。ルンバについては[KainokiKaede's diary](http://kainokikaede.hatenablog.com/entry/2018/07/24/185452)の素晴らしい記事を読んで欲しい。

View File

@@ -0,0 +1,15 @@
version: "3.0"
services:
web:
image: ghcr.io/uetchy/uechi.io
container_name: uechi.io
environment:
VIRTUAL_HOST: uechi.io
LETSENCRYPT_HOST: uechi.io
labels:
com.centurylinklabs.watchtower.enable: "true"
networks:
default:
name: webproxy
external: true

8
docker-compose.yml Normal file
View File

@@ -0,0 +1,8 @@
version: "3.0"
services:
web:
image: ghcr.io/uetchy/uechi.io
build: .
ports:
- "8080:80"

46
nginx.conf Normal file
View File

@@ -0,0 +1,46 @@
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
access_log /var/log/nginx/access.log;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
root /var/www/html;
error_page 404 /404.html;
location /404.html {
internal;
}
location = /robots.txt {
allow all;
log_not_found off;
access_log off;
}
location / {
index index.html;
try_files $uri $uri.html $uri/index.html =404;
}
location = / {
if ($http_user_agent ~ curl) {
rewrite / /TERMINAL last;
}
}
}
}

View File

@@ -1,19 +1,42 @@
{ {
"name": "uechi.io", "name": "hexo-site",
"version": "0.0.0",
"scripts": { "scripts": {
"fix-typo": "textlint _posts/*.md _pages/*.md --fix --dry-run -f diff", "build": "hexo generate",
"build": "bundle exec jekyll build", "clean": "hexo clean",
"start": "bundle exec jekyll serve --host 0.0.0.0 --port 4000 --baseurl '' --force_polling --drafts --unpublished --incremental", "deploy": "hexo deploy",
"test": "textlint _posts/*.md _pages/*.md -f pretty-error" "start": "yarn clean && hexo server --debug",
"test": "lint-staged"
},
"dependencies": {
"hexo": "^6.0.0",
"hexo-excerpt": "^1.2.1",
"hexo-feed": "^1.1.0",
"hexo-filter-mathjax": "^0.8.0",
"hexo-generator-archive": "^1.0.0",
"hexo-generator-category": "^1.0.0",
"hexo-generator-index": "^2.0.0",
"hexo-generator-tag": "^1.0.0",
"hexo-renderer-ejs": "^2.0.0",
"hexo-renderer-pandoc": "^0.3.0",
"hexo-renderer-sass": "^0.4.0",
"hexo-renderer-stylus": "^2.0.0",
"hexo-server": "^3.0.0",
"hexo-theme-landscape": "^0.0.3"
}, },
"devDependencies": { "devDependencies": {
"textlint": "^11.7.6", "lint-staged": "^10.5.4",
"textlint": "^11.9.0",
"textlint-filter-rule-whitelist": "^2.0.0", "textlint-filter-rule-whitelist": "^2.0.0",
"textlint-rule-common-misspellings": "^1.0.1", "textlint-rule-common-misspellings": "^1.0.1",
"textlint-rule-max-ten": "^2.0.4",
"textlint-rule-no-dropping-the-ra": "^1.1.3",
"textlint-rule-no-start-duplicated-conjunction": "^2.0.2", "textlint-rule-no-start-duplicated-conjunction": "^2.0.2",
"textlint-rule-preset-japanese": "^5.0.0" "textlint-rule-preset-japanese": "^6.0.1"
},
"lint-staged": {
"*.md": "textlint"
},
"hexo": {
"version": "5.4.0"
}, },
"private": true "private": true
} }

4
scaffolds/draft.md Normal file
View File

@@ -0,0 +1,4 @@
---
title: {{ title }}
tags:
---

3
scaffolds/page.md Normal file
View File

@@ -0,0 +1,3 @@
---
title: {{ title }}
---

5
scaffolds/post.md Normal file
View File

@@ -0,0 +1,5 @@
---
title: {{ title }}
date: {{ date }}
tags:
---

7
source/404.md Normal file
View File

@@ -0,0 +1,7 @@
---
title: Page Not Found
permalink: "/404"
---
> `404`
> This page could not be found

8
source/TERMINAL Normal file
View File

@@ -0,0 +1,8 @@
░█░█░█▀▀░█▀▀░█░█░▀█▀░░░░▀█▀░█▀█
░█░█░█▀▀░█░░░█▀█░░█░░░░░░█░░█░█
░▀▀▀░▀▀▀░▀▀▀░▀░▀░▀▀▀░▀░░▀▀▀░▀▀▀
GitHub: https://github.com/uetchy
Twitter: https://twitter.com/uechz
Wallpaper: https://uechi.io/wallpaper

View File

@@ -132,7 +132,7 @@ Notes.app に移行しました。
## Flash ## Flash
ニコニコ動画が見れなくなるので泣く泣く導入していましたが、公式で HTML5 に対応したので不要になりました。 ニコニコ動画が見れなくなるので泣く泣く導入していましたが、公式で HTML5 に対応したので不要になりました。
## [VirtualBox](https://www.virtualbox.org) ## [VirtualBox](https://www.virtualbox.org)

View File

@@ -4,9 +4,19 @@ date: 2017-06-16 00:00:00 +09:00
redirect_from: "/blog/2017/06/16/x11forward" redirect_from: "/blog/2017/06/16/x11forward"
--- ---
![x11-plot.png](/uploads/x11-plot.png) ![](/uploads/x11-plot.png)
## Ubuntu 16.04 # Installation
## Remote
### Arch Linux
```bash
pacman -S xorg-xauth xorg-fonts-100dpi xorg-xeyes
```
### Ubuntu 16.04
Make sure you have installed SSH, X11 and xAuth on a remote server. Make sure you have installed SSH, X11 and xAuth on a remote server.
@@ -16,12 +26,12 @@ sudo sed -i '/ForwardX11/s/.*/ForwardX11 yes/' /etc/ssh/sshd_config
sudo service ssh restart sudo service ssh restart
``` ```
## macOS Sierra ## Client (macOS Big Sur)
You also need to have X11 on your local machine. You also need to have X11 on your local machine.
``` ```
brew cask install xquartz # install X11 brew install xquartz # install X11
ssh -X <remote> ssh -X <remote>
$ xeyes # verify you have X11 $ xeyes # verify you have X11
``` ```

View File

@@ -1,7 +1,8 @@
--- ---
title: 初キャンプに必要な機材 title: 初キャンプに必要な機材
date: 2018-04-13 14:26:00 +09:00 date: 2018-04-13 14:26:00 +09:00
redirect_from: "/blog/2018/04/13/camping" redirect_from:
- "/blog/2018/04/13/camping"
--- ---
先月、大洗で初めてのキャンプ泊をした。 先月、大洗で初めてのキャンプ泊をした。

View File

@@ -3,11 +3,11 @@ title: Know your deps on package.json in seconds
date: 2018-09-02 03:23:00 +09:00 date: 2018-09-02 03:23:00 +09:00
--- ---
![screen-1.png.jpeg](/uploads/screen-1.png.jpeg)
How do you know what packages that project/library depend on and what exactly are that packages doing for? How do you know what packages that project/library depend on and what exactly are that packages doing for?
You'll want to quickly survey on them. So [npm-deps-list](https://github.com/uetchy/npm-deps-list) is here for. You'll want to quickly survey on them. So [npm-deps-list](https://github.com/uetchy/npm-deps-list) is here for.
![screen-1.png.jpeg](/uploads/screen-1.png.jpeg)
You can install them using `npm` or `yarn`. You can install them using `npm` or `yarn`.
```bash ```bash

View File

@@ -0,0 +1,84 @@
---
title: 生活の自動化
date: 2018-08-05 00:00:00 +09:00
redirect_from: "/blog/2018/08/05/life-automation"
---
生活にオートメーションを上手く取り入れ、本当にやりたいことに集中できる環境をつくりましょう。
# 洗濯の自動化
Panasonic のドラム洗濯乾燥機を使っています。威力を最大限に享受するため、タンブラー乾燥向けの普段着を揃えておくことも重要です。
洗剤は粉と液体とが一体化したジェルボール洗剤が便利です。ドラムの底にひとつ置くだけでよく、計量する必要がありません。
# 食器洗いの自動化
Panasonic の一人暮らし用コンパクト食洗乾燥機を使っています。
洗濯機と同じく、食洗機専用のジェルボール洗剤を使えば計量する手間を省けます。
# 照明の自動化
Philips Hue はインターネット経由で明るさや色相をコントロールすることができる電球です。
- 「家から離れたら消灯」
- 「家に近付いたら点灯」
- 「日が暮れたら暖色系に切り替える」
- 「23 時になったら消灯」
など多様なルールを作ることができます。外の明るさに合わせて照明の明るさを調整して、概日リズムが崩れにくいようルールを決めています。
# 空調の自動化
Nature Remo でエアコンの操作を自動化しました。
- 「湿度が高ければドライに変更」
- 「家から離れたら電源オフ」
- 「朝になったら冷房へ切り替え」
など多様なルールを作ることができます。
Nature Remo 自体はエアコン専用ではなく、赤外線で操作出来るデバイスであればなんでも操作できます。家ではテレビの電源・音量もこれで操作しています。
[Nature Remo を NodeJS で操作するライブラリ](https://github.com/uetchy/nature-remo)を作ったので触ってみてください。ライブラリ経由で温度・湿度・明度のセンサー値を取得したり、指定したモードにエアコンを切り替えることができます。
# 自動施錠・自動開錠
Qrio Lock をドアに取り付けることでオートロック・アンロックができるようになりました。
エントランスのドアに関しては、インターホンに Switch Bot を貼り付けて Shortcuts で解錠できるようにしておき、それを iPhone の背面トリプルタップで呼び出せるよう設定することでキーレスエントリー化しています。
# ホームアシスタント
Raspberry Pi に Home Assistant をインストールし、スマート家電を取りまとめるアシスタントとして使っています。Nature Remo や Hue、Switch Bot に紐づいているデバイスを Home Assistant のアプリからまとめて操作できます。
Apple Home より柔軟な自動化ルールを作ることができ、例えば「朝になったら照明とエアコンをつける(気温が高くかつ誰かが家にいる場合のみ)」といった気の利いた自動化ができます。
# 睡眠記録の自動化
Withings 改め Nokia 改め Withings の Sleep を使っています。
寝るとき身体にウェアラブルデバイスを身につけたくないので、マットレスの下に敷いておくだけで自動計測してくれるのはありがたいです。
機能としては、入眠・起床検知、心拍数記録、睡眠深度解析、いびき検出等があります。
# 体重記録の自動化
Withings の Wi-Fi Scale を使っています。体重と体脂肪率、心拍数、BMI を Wi-Fi 経由でクラウドに自動記録し、アプリで推移を確認できます。
Wi-Fi Scale には CO2 センサーもついており、部屋の二酸化炭素濃度を記録してくれます。
# オンラインスーパー
普段は業務スーパーを使いつつ、重くて量のある商品に関してはイトーヨーカドーのオンラインスーパーに頼っています。
お気に入りリストへ水、米、卵、かぼちゃなど毎回買うものを登録しておくことで、慣れれば 5 分程度で注文が完了します。あとは指定した時間に家へ商品を届けてくれます。
# 自動家計簿
Moneytree を使っています。支出を自動で食費、趣味、日用品などに仕分けてくれるため、使いすぎに気付きやすいです。無現金縛りプレイと相性が良いです。
# 気になる製品
## ルンバ
絨毯を取り除くわけにもいかないので二の足を踏んでいます。ルンバについては[KainokiKaede's diary](http://kainokikaede.hatenablog.com/entry/2018/07/24/185452)の記事を読んでください。

View File

@@ -2,8 +2,10 @@
title: 英語メモ title: 英語メモ
date: 2019-01-17T10:31:00.000+00:00 date: 2019-01-17T10:31:00.000+00:00
redirect_from: "/blog/2019/01/17/english-note" redirect_from: "/blog/2019/01/17/english-note"
--- ---
雑多なメモです。
- spin up - 立ち上げる - spin up - 立ち上げる
- woe - 悲しみ - woe - 悲しみ
- a little too - 少し〜すぎる - a little too - 少し〜すぎる
@@ -94,8 +96,6 @@ redirect_from: "/blog/2019/01/17/english-note"
> It uses the definite article before "majority of the students", as if referring to a known group. > It uses the definite article before "majority of the students", as if referring to a known group.
> Next piece is gonna be a super mega holy shit giantess 👍👍👍
> This sentence uses the indefinite article before the "majority of the students". This has the effect of introducing this group of students to the reader or the listener. > This sentence uses the indefinite article before the "majority of the students". This has the effect of introducing this group of students to the reader or the listener.
> It may give a hint that the exact number of the students that will vote is uncertain: it could be 51%, but then it could be 88%. > It may give a hint that the exact number of the students that will vote is uncertain: it could be 51%, but then it could be 88%.
@@ -125,7 +125,7 @@ redirect_from: "/blog/2019/01/17/english-note"
> learning foreign languages is for me lifelong hobby. knowledge likely to requires much time to acquiring but it never decays. > learning foreign languages is for me lifelong hobby. knowledge likely to requires much time to acquiring but it never decays.
> *sees client, whistles loudly* > _sees client, whistles loudly_
> weston comes out of nowhere running on all fours like a gorilla towards client > weston comes out of nowhere running on all fours like a gorilla towards client

View File

@@ -4,16 +4,18 @@ date: 2019-01-14 00:00:00 +09:00
redirect_from: "/blog/2019/01/14/padsize" redirect_from: "/blog/2019/01/14/padsize"
--- ---
padStart における padSize の求め方です。
$$ $$
\textrm{padSize} = \lceil \log_{10}(\mathbf{arraySize} + 1) \rceil \textrm{padSize} = \lceil \log_{10}(\mathbf{arraySize} + 1) \rceil
$$ $$
```js ```js
const padSize = Math.ceil(Math.log10(arr.length + 1)) const padSize = Math.ceil(Math.log10(arr.length + 1));
arr.forEach((item, index) => { arr.forEach((item, index) => {
console.log(`${index.padStart(padSize, '0')}: ${item}`) console.log(`${index.padStart(padSize, "0")}: ${item}`);
}) });
``` ```
結果は以下のようになる。 結果は以下のようになる。

View File

@@ -21,14 +21,14 @@ electron-builder を利用して macOS 向け Electron アプリをコード署
コード署名済みのアプリを[electron-notarize](https://github.com/electron-userland/electron-notarize)を使用して Apple Notary Service に提出します。 コード署名済みのアプリを[electron-notarize](https://github.com/electron-userland/electron-notarize)を使用して Apple Notary Service に提出します。
```js ```js
const { notarize } = require('electron-notarize') const { notarize } = require("electron-notarize");
notarize({ notarize({
appBundleId, appBundleId,
appPath, appPath,
appleId, appleId,
appleIdPassword, appleIdPassword,
ascProvider, ascProvider,
}) });
``` ```
- **appBundleId**: アプリの Bundle ID です。`package.json``build.appId`と同じものを使います。 - **appBundleId**: アプリの Bundle ID です。`package.json``build.appId`と同じものを使います。
@@ -44,33 +44,33 @@ electron-builder の afterSign フックを使用して、コード署名が済
フックスクリプトを`./scripts/after-sign-mac.js`に置きます。 フックスクリプトを`./scripts/after-sign-mac.js`に置きます。
```js ```js
const path = require('path') const path = require("path");
const { notarize } = require('electron-notarize') const { notarize } = require("electron-notarize");
const appleId = process.env.APPLE_ID const appleId = process.env.APPLE_ID;
const appleIdPassword = process.env.APPLE_PASSWORD const appleIdPassword = process.env.APPLE_PASSWORD;
const ascProvider = process.env.ASC_PROVIDER const ascProvider = process.env.ASC_PROVIDER;
const configPath = path.resolve(__dirname, '../package.json') const configPath = path.resolve(__dirname, "../package.json");
const appPath = path.resolve(__dirname, '../dist/mac/App.app') const appPath = path.resolve(__dirname, "../dist/mac/App.app");
const config = require(configPath) const config = require(configPath);
const appBundleId = config.build.appId const appBundleId = config.build.appId;
async function notarizeApp() { async function notarizeApp() {
console.log(`afterSign: Notarizing ${appBundleId} in ${appPath}`) console.log(`afterSign: Notarizing ${appBundleId} in ${appPath}`);
await notarize({ await notarize({
appBundleId, appBundleId,
appPath, appPath,
appleId, appleId,
appleIdPassword, appleIdPassword,
ascProvider, ascProvider,
}) });
console.log('afterSign: Notarized') console.log("afterSign: Notarized");
} }
exports.default = async () => { exports.default = async () => {
await notarizeApp() await notarizeApp();
} };
``` ```
`package.json``build``afterSign`を追加してコード署名が終わった後にスクリプトが実行されるようにします。 `package.json``build``afterSign`を追加してコード署名が終わった後にスクリプトが実行されるようにします。

View File

@@ -7,9 +7,7 @@ date: 2019-10-03 17:21:00 +09:00
ベンチマーク用の TypeScript プログラムを用意します。 ベンチマーク用の TypeScript プログラムを用意します。
#### `a.ts` ```ts a.ts
```ts
function a() { function a() {
const noise = Math.random() - 0.5; const noise = Math.random() - 0.5;
const offset = 1.0; const offset = 1.0;
@@ -19,9 +17,7 @@ function a() {
a(); a();
``` ```
#### `b.ts` ```ts b.ts
```ts
function b() { function b() {
const noise = Math.random() - 0.5; const noise = Math.random() - 0.5;
const offset = 2.0; const offset = 2.0;
@@ -37,9 +33,9 @@ b();
hyperfine 'ts-node a.ts' 'ts-node b.ts' -r 50 --warmup 3 --export-json ab.json hyperfine 'ts-node a.ts' 'ts-node b.ts' -r 50 --warmup 3 --export-json ab.json
``` ```
`result.json`の中身以下のようになります。 `result.json`の中身以下のようになります。
```json ```json result.json
{ {
"results": [ "results": [
{ {
@@ -87,8 +83,8 @@ hyperfine 'ts-node a.ts' 'ts-node b.ts' -r 50 --warmup 3 --export-json ab.json
この`result.json``times`配列を受け取り、2 つの分布間に有意差があるかどうかを判定します。 この`result.json``times`配列を受け取り、2 つの分布間に有意差があるかどうかを判定します。
```ts ```ts
import fs from 'fs'; import fs from "fs";
import {jStat} from 'jstat'; import { jStat } from "jstat";
const log = console.log; const log = console.log;
@@ -127,7 +123,7 @@ const Y = result.results[1].times;
const p = ttest(X, Y); const p = ttest(X, Y);
log(`p = ${p}`); log(`p = ${p}`);
log(`p < 0.05 = ${p < 0.05}`); log(`p < 0.05 = ${p < 0.05}`);
log(p < 0.05 ? 'Possibly some difference there' : 'No difference'); log(p < 0.05 ? "Possibly some difference there" : "No difference");
``` ```
ここで`X_mu`は分布 X の平均、`X_sigma`は分布 X の不偏分散です。 ここで`X_mu`は分布 X の平均、`X_sigma`は分布 X の不偏分散です。

View File

@@ -1,8 +1,8 @@
--- ---
title: Securing Local Dev Server title: Securing Local Dev Server
date: 2020-02-07 00:00:00 +0900 date: 2020-02-07 00:00:00 +0900
--- ---
Sometimes you want to interact with a local webserver with https support because of some browser APIs that are only available in an https environment. Sometimes you want to interact with a local webserver with https support because of some browser APIs that are only available in an https environment.
You can easily create a self-signed TLS cert for development purposes with [`mkcert`](https://github.com/FiloSottile/mkcert). You can easily create a self-signed TLS cert for development purposes with [`mkcert`](https://github.com/FiloSottile/mkcert).

View File

@@ -0,0 +1,155 @@
---
title: Distill Thumbnail from .afphoto and .afdesign
date: 2021-02-14T13:30:00
---
Nextcloud does not have support for generating thumbnails from Affinity Photo and Affinity Design. Fine, I'll do it myself.
# Digging Binary
Glancing at `.afphoto` and `.afdesign` in Finder, I noticed that it has a QuickLook support and an ability to show the thumbnail image. So these files should have thumbnail image somewhere inside its binary.
I wrote a piece of Node.js script to seek for [PNG signature](https://www.w3.org/TR/PNG/) inside a binary and save it as an image file.
```js afthumb.js
const fs = require("fs");
// png spec: https://www.w3.org/TR/PNG/
const PNG_SIG = Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]);
const IEND_SIG = Buffer.from([73, 69, 78, 68]);
function extractThumbnail(buf) {
const start = buf.indexOf(PNG_SIG);
const end = buf.indexOf(IEND_SIG, start) + IEND_SIG.length * 2; // IEND + CRC
return buf.subarray(start, end);
}
function generateThumbnail(input, output) {
const buf = fs.readFileSync(input);
const thumbBuf = extractThumbnail(buf);
fs.writeFileSync(output, thumbBuf);
}
generateThumbnail(process.argv[2], process.argv[3] || "output.png");
```
That's right. This script just scrapes a binary file and distill a portion of which starts with `PNG` signature and ends with `IEND`.
Now I can generate a thumbnail image from arbitrary `.afphoto` and `.afdesign` file. Let's move on delving into Nextcloud source code.
# Tweaking Nextcloud
I have a bit of experience in tweaking Nextcloud source code before, where I implemented thumbnail generator for PDFs, so it should be easier this time, hopefully.
Long story short, I got Nextcloud generates thumbnail images for Affinity files by implementing `ProviderV2` class.
```php lib/private/Preview/Affinity.php
<?php
namespace OC\Preview;
use OCP\Files\File;
use OCP\IImage;
use OCP\ILogger;
class Affinity extends ProviderV2 {
public function getMimeType(): string {
return '/application\/x-affinity-(?:photo|design)/';
}
public function getThumbnail(File $file, int $maxX, int $maxY): ?IImage {
$tmpPath = $this->getLocalFile($file);
$handle = fopen($tmpPath, 'rb');
$fsize = filesize($tmpPath);
$contents = fread($handle, $fsize);
$start = strrpos($contents, "\x89PNG");
$end = strrpos($contents, "IEND", $start);
$subarr = substr($contents, $start, $end - $start + 8 );
fclose($handle);
$this->cleanTmpFiles();
$image = new \OC_Image();
$image->loadFromData($subarr);
$image->scaleDownToFit($maxX, $maxY);
return $image->valid() ? $image : null;
}
}
```
```patch lib/private/PreviewManager.php
@@ -363,6 +365,8 @@
$this->registerCoreProvider(Preview\Krita::class, '/application\/x-krita/');
$this->registerCoreProvider(Preview\MP3::class, '/audio\/mpeg/');
$this->registerCoreProvider(Preview\OpenDocument::class, '/application\/vnd.oasis.opendocument.*/');
+ $this->registerCoreProvider(Preview\Affinity::class, '/application\/x-affinity-(?:photo|design)/');
// SVG, Office and Bitmap require imagick
if (extension_loaded('imagick')) {
```
```patch lib/composer/composer/autoload_static.php
@@ -1226,6 +1226,7 @@
'OC\\OCS\\Result' => __DIR__ . '/../../..' . '/lib/private/OCS/Result.php',
'OC\\PreviewManager' => __DIR__ . '/../../..' . '/lib/private/PreviewManager.php',
'OC\\PreviewNotAvailableException' => __DIR__ . '/../../..' . '/lib/private/PreviewNotAvailableException.php',
+ 'OC\\Preview\\Affinity' => __DIR__ . '/../../..' . '/lib/private/Preview/Affinity.php',
'OC\\Preview\\BMP' => __DIR__ . '/../../..' . '/lib/private/Preview/BMP.php',
'OC\\Preview\\BackgroundCleanupJob' => __DIR__ . '/../../..' . '/lib/private/Preview/BackgroundCleanupJob.php',
'OC\\Preview\\Bitmap' => __DIR__ . '/../../..' . '/lib/private/Preview/Bitmap.php',
```
```patch lib/composer/composer/autoload_classmap.php
@@ -1197,6 +1197,7 @@
'OC\\OCS\\Result' => $baseDir . '/lib/private/OCS/Result.php',
'OC\\PreviewManager' => $baseDir . '/lib/private/PreviewManager.php',
'OC\\PreviewNotAvailableException' => $baseDir . '/lib/private/PreviewNotAvailableException.php',
+ 'OC\\Preview\\Affinity' => $baseDir . '/lib/private/Preview/Affinity.php',
'OC\\Preview\\BMP' => $baseDir . '/lib/private/Preview/BMP.php',
'OC\\Preview\\BackgroundCleanupJob' => $baseDir . '/lib/private/Preview/BackgroundCleanupJob.php',
'OC\\Preview\\Bitmap' => $baseDir . '/lib/private/Preview/Bitmap.php',
```
![](afphoto.png)
Easy-peasy!
# Bonus: PDF thumbnail generator
Install `ghostscript` on your server to make it work.
```php lib/private/Preview/PDF.php
<?php
namespace OC\Preview;
use OCP\Files\File;
use OCP\IImage;
class PDF extends ProviderV2 {
public function getMimeType(): string {
return '/application\/pdf/';
}
public function getThumbnail(File $file, int $maxX, int $maxY): ?IImage {
$tmpPath = $this->getLocalFile($file);
$outputPath = \OC::$server->getTempManager()->getTemporaryFile();
$gsBin = \OC_Helper::findBinaryPath('gs');
$cmd = $gsBin . " -o " . escapeshellarg($outputPath) . " -sDEVICE=jpeg -sPAPERSIZE=a4 -dLastPage=1 -dPDFFitPage -dJPEGQ=90 -r144 " . escapeshellarg($tmpPath);
shell_exec($cmd);
$this->cleanTmpFiles();
$image = new \OC_Image();
$image->loadFromFile($outputPath);
$image->scaleDownToFit($maxX, $maxY);
unlink($outputPath);
return $image->valid() ? $image : null;
}
}
```

Binary file not shown.

After

Width:  |  Height:  |  Size: 437 KiB

View File

@@ -0,0 +1,18 @@
---
title: 点字の表現力
date: 2021-02-13T01:00:00
---
「n 種類の文字を表現できる点字を作らないといけなくなったらどうしよう」
例としてドット が 3 つの点字を用意した。
- 組み合わせ数は 3P3 + 3P2 + 3P1
- $f(N) = \sum_{K=N → 1} N P K$
- 2 の n 乗っぽい
- べき集合の濃度?
- 2 進数のブール配列と考えればわかりやすくなった
- ということは X 個の表現をするために必要なブール配列の長さは $\lceil\log_2 (X)\rceil$
- 例えばアルファベットなら 6 ドットの点字で表現できる
- だから英語の点字は 6 つの点で構成されている
- 点字を 18 ドットに拡張すれば Unicode 13.0 の文字すべてを表現できる

View File

@@ -0,0 +1,128 @@
---
title: 解剖学アトラス
date: 2021-06-08T00:00:00
---
いつもの幅優先探索癖。アトラスの用途は美術解剖と消化器系の構造理解。
# ノート
肉眼解剖学はアプローチの違いから局所解剖学と系統解剖学に分けられる。
体表解剖は解剖学的構造と体表の特徴との関連を視覚的に理解するための節。
微視的レベルで観察する組織学—又の名を顕微鏡解剖学—が肉眼解剖学に対置する。
他にも、胚からの成長過程に着目する発生学、部位の機能を明らかにする生理学、物質代謝の機序に興味をおく生化学等が周辺にある。
テキスト、アトラス、カラーアトラスが一冊ずつあれば事足りそう。
個人的には『グレイ解剖学』、『ネッター解剖学アトラス』、『解剖学カラーアトラス』。
余裕があれば『プロメテウス解剖学アトラス 胸部/腹部・骨盤部』。
# 教科書
## グレイ解剖学 原著第 4 版
2019(原著 2018)
- 腹膜と腸間膜の節に限ってみても、筆者の「絶対にわからせる」という強い意志を感じさせる説明によって圧倒的にわからされてしまう
- 各章は概観、局所解剖、体表解剖、臨床症例から構成されている、肉眼解剖学に的を絞った本
- 腹腔・腹膜・腸間膜関連はプロメテウスより詳しい(特に一部腸管が二次的に腹膜後器官になる過程等)
- Meckel 憩室の臨床症例が写真とともに載っている
# アトラス
## ネッター解剖学アトラス 原著第 6 版
2016(原著 2014)
- 元々ノバルティスの販促のために描かれたイラストをまとめ上げたもの
- 組織と筋肉、血管、神経がまとまって描かれており、位置関係がわかりやすい
- 断面解剖の CT と図譜両方がある(プロメテウスは CT のみ)
- グラントと比べてカラフル
## グラント解剖学図譜 第 7 版
2016(原著 2013)
- イラストは立体感を把握しやすいタッチ
## プロメテウス解剖学アトラス 解剖学総論/運動器系 第 3 版
2017(原著 2014)
- 全身の骨格から筋肉、血管、神経、リンパ系が一通り概説されている
- ポージングの参考になる関節力学の知見が豊富
- 消化器系は解説なし
- 病例と診断方法、その施術指南が特徴
## プロメテウス解剖学アトラス 口腔・頭頸部 第 2 版
2018(原著 2015)
- 脳、頭部、口腔、頸部に絞って解説
- 口腔から食道、胃までの部分に関する記述が非常に豊富
- 歯科臨床を意識した紙面構成
- 口腔・頭頸部以外の部位についての説明もざっくりされている
## プロメテウス解剖学アトラス 胸部/腹部・骨盤部 第 3 版
2020(原著 2015)
- 胸部から腹部にかけて発生学・解剖学の図説が中心
- 食道の筋の機能的構造の図解など、グレイ解剖学には載っていない内容も多い
## プロメテウス解剖学 コアアトラス 第 3 版
2016
- プロメテウス 3 巻を一冊にまとめた本で、部位ごとに内容が集約されている
- 胃の解説に 2 ページしか割かれていないなど、情報が広く浅い
# カラーアトラス
## 解剖学カラーアトラス 第 8 版 A Photographic Atlas
2016(原著 2016)
- ほとんどがリアルな解剖写真
- 写真と共に図解イラストが対照されており理解が捗る
- 図とアノテーションしか無いため、機能理解は他の本に頼る必要がある
- ユニークな点として、胎児の矢状断面図が掲載されている
## 人体解剖カラーアトラス 原著第 8 版 Clinical Atlas of Human Anatomy
- こちらも基本的にアノテーションのみだが、注釈的説明が若干多め
- 解剖学カラーアトラスと比べて 140 ページ少ない
- 腹膜のヒダの写真はこちらにしか載っていない
# アプリ
## Human Anatomy Atlas
https://apps.apple.com/jp/app/human-anatomy-atlas-2021/id1117998129?l=en
- 毎年 11 月から 12 月頃にセールをしている
# Web サイト
- 1 年生の解剖学辞典 - https://anatomy1.net/
- 医学生の教科書 - https://store.isho.jp/
# 知見
- 食道は腰椎と胸大動脈の前方、気管と心臓の後方を通る
- 横隔膜のすぐ上方に心臓、すぐ下方に胃がある
- 食道の正常な内径は 20mm
- 食道には縦走ヒダが走っているが、Z 線を超えると胃底となり模様が変化する
- 噴門括約筋は横隔膜食道裂孔の筋肉が代行しており、ジグザグ状であるので Z 線と呼ばれている(リング状に筋肉が縮まるのではなく、ジグザグ状の縦筋が縮まることで噴門を締め上げている)→ プロメテウス胸部 p. 168
- 心臓はわずかに左にずれているため、左肺は右肺より小さい
- 憩室といえば大腸だと思っていたが、食道にも発生する → プロメテウス胸部 p. 169
- 「滑り説」筋収縮のメカニズムの学説のひとつ
# 用語
- 翻転(ほんてん) - 組織をひっくりかえすこと
- 腋窩(えきか)
- 網嚢孔(もうのうこう)
- 横紋筋(おうもんきん)と平滑筋(へいかつきん)
- 蠕動運動(ぜんどう—)

View File

@@ -0,0 +1,869 @@
---
title: Comprehensive Guide for Setting Up Arch Linux
date: 2021-02-12T00:00:00
---
This note includes all commands I typed when I set up Arch Linux on my new server.
> PSA: I published a toolchain for building AUR packages in a clean-room docker container
> <https://github.com/uetchy/archpkgs>
# Setup
## Wipe whole disk
```bash
wipefs -a /dev/sda
```
## Create partition
```bash
parted
```
```bash
select /dev/sda
mktable gpt
mkpart EFI fat32 0 512MB # EFI
mkpart Arch ext4 512MB 100% # Arch
set 1 esp on # flag partition 1 as ESP
quit
```
## Install file-system
```bash
mkfs.vfat -F 32 /dev/sda1 # EFI
mkfs.ext4 /dev/sda2 # Arch
e2fsck -cc -C 0 /dev/sda2 # fsck
```
## Mount disk
```bash
mkdir -p /mnt/boot
mount /dev/sda2 /mnt
mount /dev/sda1 /mnt/boot
```
## Install base & Linux kernel
```bash
# choose between 'linux' or 'linux-lts'
pacstrap /mnt base linux-lts linux-firmware
genfstab -U /mnt >> /mnt/etc/fstab
arch-chroot /mnt
```
```bash
pacman -S reflector
reflector --protocol https --latest 30 --sort rate --save /etc/pacman.d/mirrorlist --verbose # optimize mirror list
```
## Install essentials
```bash
pacman -S vim man-db man-pages git base-devel
```
## Locales
```bash
ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
hwclock --systohc
vim /etc/locale.gen & locale-gen
echo "LANG=en_US.UTF-8" > /etc/locale.conf
```
## add fstab entries
```ini /etc/fstab
# backup
UUID=<UUID> /mnt/backup ext4 defaults 0 2
# archive (do not prevent boot even if fsck fails)
UUID=<UUID> /mnt/archive ext4 defaults,nofail,x-systemd.device-timeout=4 0 2
```
Find `<UUID>` from the output of `lsblk -f`.
```bash
findmnt --verify --verbose # verify fstab
```
## Install bootloader
```bash
pacman -S \
grub \
efibootmgr \
amd-ucode # AMD microcode
grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=GRUB
vim /etc/default/grub
# GRUB_TIMEOUT=3
# GRUB_DISABLE_SUBMENU=y
grub-mkconfig -o /boot/grub/grub.cfg
```
- [GRUB/Tips and tricks - ArchWiki](https://wiki.archlinux.org/title/GRUB/Tips_and_tricks)
## Setup network
```bash
hostnamectl set-hostname takos
hostnamectl set-chassis server
```
```ini /etc/hosts
127.0.0.1 localhost
::1 localhost
127.0.0.1 takos
```
See https://systemd.network/systemd.network.html and https://wiki.archlinux.org/title/Systemd-networkd, and <https://blog.ivansmirnov.name/set-up-pihole-using-docker-macvlan-network/>.
```ini /etc/systemd/network/wired.network
[Match]
Name=enp5s0
[Network]
#DHCP=yes
Address=10.0.1.2/24
Gateway=10.0.1.1
DNS=10.0.1.100 # self-hosted DNS resolver
DNS=1.1.1.1 # Cloudflare for the fallback DNS server
MACVLAN=dns-shim # to handle local dns lookup to 10.0.1.100 which is managed by Docker macvlan driver
```
```ini /etc/systemd/network/dns-shim.netdev
# to handle local dns lookup to 10.0.1.100
[NetDev]
Name=dns-shim
Kind=macvlan
[MACVLAN]
Mode=bridge
```
```ini /etc/systemd/network/dns-shim.network
# to handle local dns lookup to 10.0.1.100
[Match]
Name=dns-shim
[Network]
IPForward=yes
[Address]
Address=10.0.1.103/32
Scope=link
[Route]
Destination=10.0.1.100/30
```
`ip` equivalent to the above config:
```bash
ip link add dns-shim link enp5s0 type macvlan mode bridge # add macvlan shim interface
ip a add 10.0.1.103/32 dev dns-shim # assign the interface an ip address
ip link set dns-shim up # enable the interface
ip route add 10.0.1.100/30 dev dns-shim # route macvlan subnet (.100 - .103) to the interface
```
```bash
systemctl enable --now systemd-networkd
networkctl status
ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf
# for self-hosted dns resolver
sed -r -i -e 's/#?DNSStubListener=yes/DNSStubListener=no/g' -e 's/#DNS=/DNS=10.0.1.100/g' /etc/systemd/resolved.conf
systemctl enable --now systemd-resolved
resolvectl status
resolvectl query ddg.gg
drill ddg.gg
```
If `networkctl` keep showing `enp5s0` as `degraded`, then run `ip addr add 10.0.1.2/24 dev enp5s0 ` to manually assign static IP address for the workaround.
## Finalize
```bash
exit # leave chroot
umount -R /mnt
reboot
```
## NTP
```bash
timedatectl set-ntp true
timedatectl status
```
## Shell
```bash
pacman -S zsh
chsh -s /bin/zsh
git clone https://github.com/uetchy/dotfiles ~/.dotfiles
yay -S ruby pyenv exa antibody direnv fd ripgrep fzy peco ghq-bin hub neofetch tmux git-delta lazygit jq lostfiles ncdu htop rsync youtube-dl prettier tree age informant
usermod -aG informant <user>
cd ~/.dotfiles
./dot link zsh -f
reload
```
## Setup operator user (i.e. user without superuser privilege)
```bash
passwd # change root passwd
useradd -m -s /bin/zsh <user> # add local user
passwd <user> # change local user password
userdbctl # verify users
userdbctl group # verify groups
pacman -S sudo
echo "%sudo ALL=(ALL) NOPASSWD:/usr/bin/pacman" > /etc/sudoers.d/pacman # allow users in sudo group to run pacman without password (optional)
groupadd sudo
usermod -aG sudo <user> # add local user to sudo group
visudo -c
```
## SSH
```bash
pacman -S openssh
vim /etc/ssh/sshd_config
systemctl enable --now sshd
```
on the host machine:
```bash
ssh-copy-id <user>@<ip>
```
```bash:$HOME/.ssh/rc
if [ ! -S ~/.ssh/ssh_auth_sock ] && [ -S "$SSH_AUTH_SOCK" ]; then
ln -sf $SSH_AUTH_SOCK ~/.ssh/ssh_auth_sock
fi
```
See also: [Happy ssh agent forwarding for tmux/screen · Reboot and Shine](https://werat.dev/blog/happy-ssh-agent-forwarding/)
## AUR
```bash
git clone https://aur.archlinux.org/yay.git
cd yay
makepkg -si
```
## S.M.A.R.T.
```bash
pacman -S smartmontools
systemctl enable --now smartd
smartctl -t short /dev/sda
smartctl -l selftest /dev/sda
```
## NVIDIA drivers
```bash
pacman -S nvidia-lts # 'nvidia' for 'linux' package
reboot
nvidia-smi # test runtime
```
## Docker
https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/arch-overview.html
```bash
pacman -S docker docker-compose
yay -S nvidia-container-runtime
systemctl enable --now docker
```
```json /etc/docker/daemon.json
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m", // default: -1 (unlimited)
"max-file": "3" // default: 1
},
"runtimes": {
// for docker-compose
"nvidia": {
"path": "/usr/bin/nvidia-container-runtime",
"runtimeArgs": []
}
}
}
```
```bash
systemctl restart docker
usermod -aG docker <user>
# to create mandatory device files on /dev
docker run --gpus all nvidia/cuda:10.2-cudnn7-runtime nvidia-smi
GPU_OPTS=(--gpus all --device /dev/nvidia0 --device /dev/nvidiactl --device /dev/nvidia-modeset --device /dev/nvidia-uvm --device /dev/nvidia-uvm-tools)
docker run --rm -it ${GPU_OPTS} nvidia/cuda:10.2-cudnn7-runtime nvidia-smi
docker run --rm -it ${GPU_OPTS} tensorflow/tensorflow:1.14.0-gpu-py3 bash
docker create network webproxy
```
### Use `journald` log driver in Docker Compose
```yaml
services:
web:
logging:
driver: "journald"
options:
tag: "{{.ImageName}}/{{.Name}}/{{.ID}}" # default: "{{.ID}}"
```
- [Configure logging drivers | Docker Documentation](https://docs.docker.com/config/containers/logging/configure/)
# Additional setup
## Fail2ban
```
pacman -S fail2ban
```
```ini /etc/fail2ban/filter.d/bad-auth.conf
[INCLUDES]
before = common.conf
[Definition]
failregex = .* client login failed: .+ client:\ <HOST>
ignoreregex =
```
```ini /etc/fail2ban/jail.local
[DEFAULT]
ignoreip = 127.0.0.1/8 10.0.1.0/24
[sshd]
enabled = true
port = 22,10122
bantime = 1h
mode = aggressive
# https://github.com/Mailu/Mailu/blob/master/docs/faq.rst#do-you-support-fail2ban
[mailu]
enabled = true
backend = systemd
journalmatch = CONTAINER_NAME=mail_front_1
filter = bad-auth
findtime = 1h
maxretry = 3
bantime = 1w
chain = DOCKER-USER
banaction = iptables-allports
```
```patch /etc/systemd/system/fail2ban.service
- After=network.target iptables.service firewalld.service ip6tables.service ipset.service nftables.service
+ After=network.target iptables.service firewalld.service ip6tables.service ipset.service nftables.service docker.service
```
```bash
systemctl enable --now fail2ban
fail2ban-client status sshd
```
## Telegraf
```bash
yay -S telegraf
```
```ini /etc/telegraf/telegraf.conf
# Global tags can be specified here in key="value" format.
[global_tags]
# Configuration for telegraf agent
[agent]
interval = "15s"
round_interval = true
metric_batch_size = 1000
metric_buffer_limit = 10000
collection_jitter = "0s"
flush_interval = "10s"
flush_jitter = "0s"
precision = ""
hostname = ""
omit_hostname = false
# Read InfluxDB-formatted JSON metrics from one or more HTTP endpoints
[[outputs.influxdb]]
urls = ["http://127.0.0.1:8086"]
database = "<db>"
username = "<user>"
password = "<password>"
# Read metrics about cpu usage
[[inputs.cpu]]
percpu = true
totalcpu = true
collect_cpu_time = false
report_active = false
# Read metrics about disk usage by mount point
[[inputs.disk]]
ignore_fs = ["tmpfs", "devtmpfs", "devfs", "iso9660", "overlay", "aufs", "squashfs"]
# Read metrics about disk IO by device
[[inputs.diskio]]
# Get kernel statistics from /proc/stat
[[inputs.kernel]]
# Read metrics about memory usage
[[inputs.mem]]
# Get the number of processes and group them by status
[[inputs.processes]]
# Read metrics about system load & uptime
[[inputs.system]]
# Read metrics about network interface usage
[[inputs.net]]
interfaces = ["enp5s0"]
# Read metrics about docker containers
[[inputs.docker]]
endpoint = "unix:///var/run/docker.sock"
perdevice = false
total = true
[[inputs.fail2ban]]
interval = "15m"
use_sudo = true
# Pulls statistics from nvidia GPUs attached to the host
[[inputs.nvidia_smi]]
timeout = "30s"
[[inputs.http_response]]
interval = "5m"
urls = [
"https://example.com"
]
# Monitor sensors, requires lm-sensors package
[[inputs.sensors]]
interval = "60s"
remove_numbers = false
# Run executable as long-running input plugin
[[inputs.execd]]
interval = "15s"
command = ["/metrics.sh"]
name_override = "metrics"
signal = "STDIN"
restart_delay = "20s"
data_format = "logfmt"
```
```ini /etc/sudoers.d/telegraf
Cmnd_Alias FAIL2BAN = /usr/bin/fail2ban-client status, /usr/bin/fail2ban-client status *
telegraf ALL=(root) NOEXEC: NOPASSWD: FAIL2BAN
Defaults!FAIL2BAN !logfile, !syslog, !pam_session
```
```bash
chmod 440 /etc/sudoers.d/telegraf
usermod -aG docker telegraf
telegraf -config /etc/telegraf/telegraf.conf -test
systemctl enable --now telegraf
```
## cfddns
Dynamic DNS for Cloudflare.
> Start [the GitHub repo](https://github.com/uetchy/cfddns) if you like :)
```
yay -S cfddns sendmail
```
```yml /etc/cfddns/cfddns.yml
token: <token>
notification:
enabled: true
from: cfddns@localhost
to: me@example.com
```
```ini /etc/cfddns/domains
example.com
dev.example.com
example.org
```
```
systemctl enable --now cfddns
```
## Backup
```bash
pacman -S restic
```
```ini /etc/backup/restic.service
[Unit]
Description=Daily Backup Service
[Service]
Type=simple
Nice=19
IOSchedulingClass=2
IOSchedulingPriority=7
ExecStart=/etc/backup/run.sh
```
```ini /etc/backup/restic.timer
[Unit]
Description=Daily Backup Timer
[Timer]
WakeSystem=false
OnCalendar=*-*-* 14:00
RandomizedDelaySec=5min
[Install]
WantedBy=timers.target
```
```bash /etc/backup/run.sh
#!/bin/bash -ue
# usage: run.sh
# https://restic.readthedocs.io/en/latest/040_backup.html#
export RESTIC_REPOSITORY=/path/to/backup
export RESTIC_PASSWORD=<passphrase>
export RESTIC_PROGRESS_FPS=1
# system
restic backup --tag system -v \
--one-file-system \
--exclude .cache \
--exclude .venv \
--exclude .vscode-server \
--exclude .vscode-server-insiders \
--exclude TabNine \
--exclude node_modules \
--exclude /var/lib/docker/overlay2 \
/ /boot
# data
restic backup --tag data -v \
--exclude 'appdata_*/preview' \ # nextcloud cache
--exclude 'appdata_*/dav-photocache' \ # nextcloud cache
/mnt/data
# prune
restic forget --prune --group-by tags \
--keep-within-daily 7d \
--keep-within-weekly 1m \
--keep-within-monthly 3m
# verify
restic check
```
```bash /etc/backup/show.sh
#!/bin/bash
# usage: show.sh <file|directory>
# https://restic.readthedocs.io/en/latest/050_restore.html
export RESTIC_REPOSITORY=/path/to/backup
export RESTIC_PASSWORD=<passphrase>
export RESTIC_PROGRESS_FPS=1
TARGET=${1:-$(pwd)}
MODE="ls -l"
if [[ -f $TARGET ]]; then
TARGET=$(realpath ${TARGET})
MODE=dump
fi
TAG=$(restic snapshots --json | jq -r '[.[].tags[0]] | unique| .[]' | fzy)
ID=$(restic snapshots --tag $TAG --json | jq -r ".[] | [.time, .short_id] | @tsv" | fzy | awk '{print $2}')
>&2 echo "Command: restic ${MODE} ${ID} ${TARGET}"
restic $MODE $ID ${TARGET}
```
```bash /etc/backup/restore.sh
#!/bin/bash
# https://restic.readthedocs.io/en/latest/050_restore.html
export RESTIC_REPOSITORY=/path/to/backup
export RESTIC_PASSWORD=<passphrase>
export RESTIC_PROGRESS_FPS=1
TARGET=${1:?Specify TARGET}
TARGET=$(realpath ${TARGET})
TAG=$(restic snapshots --json | jq -r '[.[].tags[0]] | unique | .[]' | fzy)
ID=$(restic snapshots --tag $TAG --json | jq -r ".[] | [.time, .short_id] | @tsv" | fzy | awk '{print $2}')
>&2 echo "Command: restic restore ${ID} -i ${TARGET} -t /"
read -p "Press enter to continue"
restic restore $ID -i ${TARGET} -t /
```
```bash
chmod 700 /etc/backup/{run,show}.sh
ln -sf /etc/backup/restic.{service,timer} /etc/systemd/system/
systemctl enable --now restic
```
## Kubernetes
```bash
pacman -S minikube kubectl
minikube start --cpus=max
kubectl taint nodes --all node-role.kubernetes.io/master- # to allow allocating pods to the master node
minikube ip
kubectl cluster-info
kubectl get cm -n kube-system kubeadm-config -o yaml
```
- [Kubernetes - ArchWiki](https://wiki.archlinux.org/index.php/Kubernetes)
- [Kubernetes Ingress Controller with NGINX Reverse Proxy and Wildcard SSL from Let's Encrypt - Shogan.tech](https://www.shogan.co.uk/kubernetes/kubernetes-ingress-controller-with-nginx-reverse-proxy-and-wildcard-ssl-from-lets-encrypt/)
## Audio
```bash
pacman -S alsa-utils # maybe requires rebooting system
usermod -aG audio <user>
# list devices as root
aplay -l
arecord -L
cat /proc/asound/cards
# test speaker
speaker-test -c2
# test mic
arecord -vv -Dhw:2,0 -fS32_LE mic.wav
aplay mic.wav
# gui mixer
alsamixer
# for Mycroft.ai
pacman -S pulseaudio pulsemixer
pulseaudio --start
pacmd list-cards
```
```conf /etc/pulse/default.pa
# INPUT/RECORD
load-module module-alsa-source device="default" tsched=1
# OUTPUT/PLAYBACK
load-module module-alsa-sink device="default" tsched=1
# Accept clients -- very important
load-module module-native-protocol-unix
load-module module-native-protocol-tcp
```
```conf /etc/asound.conf
pcm.mic {
type hw
card M96k
rate 44100
format S32_LE
}
pcm.speaker {
type plug
slave {
pcm "hw:1,0"
}
}
pcm.!default {
type asym
capture.pcm "mic"
playback.pcm "speaker"
}
#defaults.pcm.card 1
#defaults.ctl.card 1
```
- [PulseAudio as a minimal unintrusive dumb pipe to ALSA](https://wiki.archlinux.org/title/PulseAudio/Examples#PulseAudio_as_a_minimal_unintrusive_dumb_pipe_to_ALSA)
- [SoundcardTesting - AlsaProject](https://www.alsa-project.org/main/index.php/SoundcardTesting)
- [Advanced Linux Sound Architecture/Troubleshooting - ArchWiki](https://wiki.archlinux.org/index.php/Advanced_Linux_Sound_Architecture/Troubleshooting#Microphone)
- [ALSA project - the C library reference: PCM (digital audio) plugins](https://www.alsa-project.org/alsa-doc/alsa-lib/pcm_plugins.html)
- [Asoundrc - AlsaProject](https://www.alsa-project.org/wiki/Asoundrc)
## Firewall
```bash
pacman -S firewalld
systemctl enable --now firewalld
```
See [Introduction to Netfilter – To Linux and beyond !](https://home.regit.org/netfilter-en/netfilter/).
# Maintenance
## Quick checkups
```bash
htop # show task overview
systemctl --failed # show failed units
free -h # show memory usage
lsblk -f # show disk usage
networkctl status # show network status
userdbctl # show users
nvidia-smi # verify nvidia cards
ps aux | grep "defunct" # find zombie processes
```
## Delve into system logs
```bash
journalctl -p err -b-1 -r # show error logs from previous boot in reverse order
journalctl -u sshd -f # tail logs from sshd unit
journalctl --no-pager -n 25 -k # show latest 25 logs from the kernel without pager
journalctl --since=yesterday --until "2020-07-10 15:10:00" # show logs within specific time range
journalctl CONTAINER_NAME=service_web_1 # show error from docker container named 'service_web_1'
journalctl _PID=2434 -e # filter logs based on PID and jump to the end of the logs
journalctl -g 'timed out' # filter logs based on regular expression. if the pattern is all lowercase, matching is case insensitive
```
- g - go to the first line
- G - go to the last line
- / - search for the string
## Force overriding installation
```bash
pacman -S <pkg> --overwrite '*'
```
## Check memory modules
```bash
pacman -S lshw dmidecode
lshw -short -C memory # lists installed mems
dmidecode # shows configured clock speed
```
## File-system related issues checklist
```bash
smartctl -H /dev/sdd
# umount the drive before this ops
e2fsck -C 0 -p /dev/sdd1 # preen
e2fsck -C 0 -cc /dev/sdd1 # badblocks
```
# Common issues
## Longer SSH login (D-bus glitch)
```bash
systemctl restart systemd-logind
systemctl restart polkit
```
- [A comprehensive guide to fixing slow SSH logins – JRS Systems: the blog](https://jrs-s.net/2017/07/01/slow-ssh-logins/)
## Annoying `systemd-homed is not available` log messages
Move `pam_unix` before `pam_systemd_home`.
```ini /etc/pam.d/system-auth
#%PAM-1.0
auth required pam_faillock.so preauth
# Optionally use requisite above if you do not want to prompt for the password
# on locked accounts.
auth [success=2 default=ignore] pam_unix.so try_first_pass nullok
-auth [success=1 default=ignore] pam_systemd_home.so
auth [default=die] pam_faillock.so authfail
auth optional pam_permit.so
auth required pam_env.so
auth required pam_faillock.so authsucc
# If you drop the above call to pam_faillock.so the lock will be done also
# on non-consecutive authentication failures.
account [success=1 default=ignore] pam_unix.so
-account required pam_systemd_home.so
account optional pam_permit.so
account required pam_time.so
password [success=1 default=ignore] pam_unix.so try_first_pass nullok shadow
-password required pam_systemd_home.so
password optional pam_permit.so
session required pam_limits.so
session required pam_unix.so
session optional pam_permit.so
```
- [[solved] pam fails to find unit dbus-org.freedesktop.home1.service / Newbie Corner / Arch Linux Forums](https://bbs.archlinux.org/viewtopic.php?id=258297)
## Annoying systemd-journald-audit log
```ini /etc/systemd/journald.conf
Audit=no
```
## Missing `/dev/nvidia-{uvm*,modeset}`
This occurs after updating linux kernel.
- Run `docker run --rm --gpus all --device /dev/nvidia0 --device /dev/nvidiactl --device /dev/nvidia-modeset --device /dev/nvidia-uvm --device /dev/nvidia-uvm-tools -it nvidia/cuda:10.2-cudnn7-runtime nvidia-smi` once.
## `[sudo] Incorrect password` while password is correct
```bash
faillock --reset
```
# Useful links
- [General recommendations](https://wiki.archlinux.org/index.php/General_recommendations#Users_and_groups)
- [System maintenance](https://wiki.archlinux.org/index.php/System_maintenance)
- [Improving performance](https://wiki.archlinux.org/index.php/Improving_performance#Know_your_system)
- [General troubleshooting - ArchWiki](https://wiki.archlinux.org/title/General_troubleshooting)
- [Stress testing - ArchWiki](https://wiki.archlinux.org/title/Stress_testing#Stressing_memory)
- [udev - ArchWiki](https://wiki.archlinux.org/title/Udev#Debug_output)
- [[HOWTO] Repair Broken system, system without a kernel / Forum & Wiki discussion / Arch Linux Forums](https://bbs.archlinux.org/viewtopic.php?id=18066)
- [Archboot - ArchWiki](https://wiki.archlinux.org/title/Archboot)
- [Restic Documentation — restic 0.12.1 documentation](https://restic.readthedocs.io/en/stable/)

View File

@@ -0,0 +1,102 @@
---
title: OAuth 2.0 と JWT 関連 RFC
date: 2021-02-11
---
個人的な調査のために OAuth 2.0 と JWT 関連 RFC を発行日順に並べた。
## [RFC6749](https://tools.ietf.org/html/rfc6749) — The OAuth 2.0 Authorization Framework
2012 年 10 月
OAuth 1.0a に代わる新たな認証基盤 OAuth 2.0 のコアを規定しており、特筆すべき点がいくつかある。
- `access_token` の内容は規定されておらず、ベンダーに委ねられている
- JWS でもなんでもいい
- リソースサーバーに `access_token` を渡す方法は規定されていない(同月発行の RFC6750 で規定された)
### Authorization Grant
トークンエンドポイントで`access_token`を発行してもらう際に使用できる Grant (許可証)は、提案中の拡張仕様を含めて 5 つある。
1. Authorization Code Grant: [RFC6749 – Section 1.3.1](https://tools.ietf.org/html/rfc6749#section-1.3.1)
1. `grant_type=authorization_code`
2. Authorization Code Grant with PKCE
2. Implicit Flow: [RFC6749 – Section 1.3.2](https://tools.ietf.org/html/rfc6749#section-1.3.2)
1. もともと CORS (Cross Origin Resource Sharing) が登場する以前の SPA で、POST リクエストを回避しつつ Access Token を得る"妥協案"として策定された
2. CSRF 耐性が無い ([RFC6819 - Section 4.4.2.5](https://tools.ietf.org/html/rfc6819#section-4.4.2.5))ため、使うべきではない
3. Resource Owner Password Credentials Grant: [RFC6749 – Section 1.3.3](https://tools.ietf.org/html/rfc6749#section-1.3.3)
1. 直接パスワードで認証する形式
4. Client Credentials Grant: [RFC6749 – Section 1.3.4](https://tools.ietf.org/html/rfc6749#section-1.3.4)
1. クライアントシークレットでトークンを取得する形式。
5. Device Grant: [RFC Draft — OAuth 2.0 Device Authorization Grant](https://tools.ietf.org/html/draft-ietf-oauth-device-flow-15)
1. 入力機器が無い場合もある組み込みデバイス向けの認証フロー
## [RFC6750](https://tools.ietf.org/html/rfc6750) — The OAuth 2.0 Authorization Framework: Bearer Token Usage
2012 年 10 月
OAuth 2.0 において、`access_token`をリソースサーバーに渡す手法を規定する。OAuth 2.0 JWT Bearer Token Flow**ではない**。
手法として 3 つが挙げられている。
1. Bearer Token (**SHOULD**)
2. Form Encoded Parameters (SHOULD NOT)
3. URI Query Parameters (SHOULD NOT)
## [OICD](https://openid.net/specs/openid-connect-core-1_0.html) — OpenID Connect Core 1.0
2014 年 11 月
OAuth 2.0 の上にいくつか仕様を足したサブセット。
## [RFC7515](https://tools.ietf.org/html/rfc7515) — JSON Web Signature (JWS)
2015 年 5 月
JSON ベースの署名プロトコル。
## [RFC7516](https://tools.ietf.org/html/rfc7516) — JSON Web Encryption (JWE)
2015 年 5 月
JSON ベースの暗号化プロトコル。
## [RFC7517](https://tools.ietf.org/html/rfc7517) — JSON Web Key (JWK)
2015 年 5 月
JWT の署名チェックに用いる公開鍵を配信するためのプロトコル。
## [RFC7518](https://tools.ietf.org/html/rfc7518) — JSON Web Algorithms (JWA)
2015 年 5 月
JWS、JWE、JWK で利用されるアルゴリズム (alg)やその他プロパティを規定する。
## [RFC7519](https://tools.ietf.org/html/rfc7519) — JSON Web Token (JWT)
2015 年 5 月
JWT は JSON を利用して Assertion を生成するための仕様。
## [RFC7521](https://tools.ietf.org/html/rfc7521) — Assertion Framework for OAuth 2.0 Client Authentication and Authorization Grants
2015 年 5 月
任意の Assertion を OAuth 2.0 Client Authentication の Client Credentials として使ったり、あるいは Authorization Grant として Access Token と交換するための仕様。
トークンエンドポイントに強化されたクライアント認証を付与する。続く RFC で、それぞれ SAML と JWT を使用したパターンを規定している。
**OAuth 2.0 JWT Bearer Token Flow**とも呼ばれている。
- [RFC7522](https://tools.ietf.org/html/rfc7522) — Security Assertion Markup Language (**SAML**) 2.0 Profile for OAuth 2.0 Client Authentication and Authorization Grants (2015 年 5 月)
- [RFC7523](https://tools.ietf.org/html/rfc7523) — JSON Web Token (**JWT**) Profile for OAuth 2.0 Client Authentication and Authorization Grants (2015 年 5 月)
2015 年 5 月 https://tools.ietf.org/html/rfc7523
## [RFC Draft](https://tools.ietf.org/html/draft-ietf-oauth-access-token-jwt-02) — JSON Web Token (JWT) Profile for OAuth 2.0 Access Tokens
2019 年 7 月
リソースサーバーへ渡す Access Token に JWT を使用することを定めている。

View File

@@ -0,0 +1,26 @@
---
title: "[].map(parseInt)"
date: 2021-02-14T11:30:00
---
Fun fact: `[0xa, 0xa, 0xa].map(parseInt)` yields `[10, NaN, 2]`.
# Why
```js
parseInt(0xa, 0, [0xa, 0xa, 0xa]);
```
The second argument is `0` so the first argument going to be treated as decimal number becoming `10`.
```js
parseInt(0xa, 1, [0xa, 0xa, 0xa]);
```
The second argument is `1` which is invalid as a radix, so the result ends up with `NaN`.
```js
parseInt(0xa, 2, [0xa, 0xa, 0xa]);
```
The second argument is `2` meaning the first argument going to be handled as a binary number. `0xa` is `10` in binary, which results in `2` in decimal form.

View File

@@ -0,0 +1,70 @@
---
title: 新しい自宅サーバーの構成
date: 2021-02-13T00:00:00
---
10 年ぶりにサーバーを更新した。初めての AMD、初めての DDR4、初めての NVM Express!
# 用途
- 各種セルフホスト (Docker)
- Docker Swarm / K8s のマスター
- 計算実験
- VS Code Remote SSH のホストマシン
- VPN 他
# スペック
重いタスクを並列してやらせたいので最優先は CPU とメモリ。メモリは[DDR4-3200 32GBx2](https://shop.tsukumo.co.jp/goods/4582353591719/) を、CPU は昨今のライブラリのマルチコア対応を勘案して [Ryzen 9 3950X](https://www.amd.com/en/products/cpu/amd-ryzen-9-3950x) を選んだ。CPU クーラーは静音性を考えて Noctua の [NH-D15 Black](https://noctua.at/en/nh-d15) 。
> 結果から言うとメモリは 64GB では足りなかった。巨大な Pandas データフレームを並列処理したり、DeepSpeed でモデルの重みをオフロードするたびに OOM が発動してしまう。最終的に 128GB まで増やす羽目になった。
> 追記: メモリ異常を起因とするシステム誤動作により、`/sbin` 以下がゼロ上書きされカーネルが起動しなくなる災害が起きた。後日 ECC 付きのメモリに交換してからは、現在に至るまでメモリ関連の異常は発生していない。常時稼働するサーバーには最初から ECC メモリを選ぼう。
GPU は古いサーバーに突っ込んでいた NVIDIA GeForce GTX TITAN X (Maxwell)を流用した。グラフィックメモリが 12GB ちょっとしかないが、最大ワークロード時でも 5GB は残るので今のところ十分。
> 結果から言うと GPT-J や Megatron-LM を始めとした億パラメータ級のモデルを学習・推論させるには、DeepSpeed の助けがあったとしても最低 16GB の VRAM が必要だった。
記憶装置は WD HDD 3TB 2 台と Samsung 970 EVO Plus 500GB M.2 PCIe、そして古いサーバーから引っこ抜いた Samsung 870 EVO Plus 500GB SSD 。NVMe メモリは OS 用、SSD/HDD はデータとバックアップ用にする。
マザーボードは、X570 と比較して実装されているコンデンサーやパーツがサーバー向きだと感じた[ASRock B550 Taichi](https://www.asrock.com/mb/AMD/B550%20Taichi/) にした。
電源は今後 GPU を追加することを考えて [Seasonic PRIME TX 850](https://seasonic.com/prime-tx) を選んだ。実際にサーバーを稼働させながら使用電力を計測したところ、アイドル時に 180W 前後、フル稼働時でも 350W を超えない程度だった。
ケースは Fractal Design の [Meshify 2](https://www.fractal-design.com/products/cases/meshify/meshify-2/Black/) 。
OS は長年付き合ってきた Ubuntu と袂を分かち、[Arch Linux](https://archlinux.org/) を選んだ。ミニマルと実用の間のバランスが取れていて好み。
Arch Linux のセットアップは[個別に記事](https://uechi.io/blog/installing-arch-linux/)を書いた。
また、AUR (Arch User Repository)にパッケージを公開したい人向けに、Docker 自動ビルド・テストツールを[GitHub で公開](https://github.com/uetchy/archpkgs)した。
# パーツ選定時のポイント
- [WikiChip](https://en.wikichip.org/wiki/WikiChip)で CPU のモデルやスペックを調査する
- [PCPartPicker](https://jp.pcpartpicker.com/)でパーツのコスト計算をする
- [Bottleneck Calculator](https://pc-builds.com/calculator/)で CPU と GPU の組み合わせを選び、そのうちどちらが性能のボトルネックになるか調べる
- [UserBenchmark](https://www.userbenchmark.com/)でユーザーが投稿したベンチマーク結果を眺める
- [Linux Hardware Database](https://linux-hardware.org/) を見て、インストールする予定の Linux ディストリとパーツの相性をチェックする
- CPU クーラーは大口径の方が静か
- PSU は Seasonic が評判良い
- 東芝 D01 が HGST の系譜
- [B550](https://www.amd.com/en/chipsets/b550) は長期運用に向いている(らしい)
- B520 は廉価版
- TSUKUMO eX. の自作 PC コーナーのスタッフはガチ勢なので信頼できる
- 不明な部分があれば根掘り葉掘り聞く
# 組立ての勘所
- 少なくとも 1 年間はすべての箱・書類を取っておく(特にメモリは箱自体が保証書代わりになっている場合がある)
- 筐体は無視してまずマザボ、CPU、クーラー、(オンボードグラフィックが無い CPU なら)グラボ、そして電源を繋いで通電・動作テストをする
- [MemTest86](https://www.memtest86.com/)でメモリの動作テストを最後までやる(エラーが出たら交換依頼)
- USB ブートで OS の起動確認
- Ethernet が死んでいる場合は USB-Ethernet アダプターでまずネットを確保する
- ほとんどの場合 Linux カーネルのバージョンを上げると(デバイスドライバーも新しくなり)直る
- Arch Linux の場合: `linux-lts`が駄目なら`linux`に切り替えて試す
- Ubuntu の場合: [kernel.ubuntu.com](https://kernel.ubuntu.com/~kernel-ppa/mainline/?C=N;O=D) から探してアップデートする([https://itsfoss.com/upgrade-linux-kernel-ubuntu/](https://itsfoss.com/upgrade-linux-kernel-ubuntu/))
- 駄目ならマザボまたはアダプターメーカーからアップデートを探す
- 安い筐体のネジは柔いことがあるため、強く押し込みながら少しずつ回す
- 山が潰れてきたらゴムシートを挟む
- すべて動いたら、[Linux Hardware Database に Probe を送信](https://linux-hardware.org/index.php?view=howto)して貢献

View File

@@ -0,0 +1,148 @@
---
title: 最小送金回数で精算する割り勘アルゴリズム
date: 2021-02-14T00:00:00
---
大人数で旅行を楽しんだあとに待っているのは耐え難き精算・送金処理だ。
次回から楽をするためにも、送金回数を最小化する制約で精算表を作る方法を考えよう。
# tl;dr
アイディアは「最も支払わなかった人が最も支払った人に払えるだけ払う ⇢ 債権を再計算して繰り返す」
1. 全員の出費を算出(払い過ぎは正、払わなさすぎは負の数)
2. 降順でソート(出費過多が先頭)
3. リストの最後(最大債務者, 出費=L)がリストの最初(最大債権者, F)に $\min(F, |L|)$ を支払ってバランスを再計算
4. 全員のバランスが 0 になるまで 2-3 を繰り返す
# 実験
実際にコードを書いて本当に望んでいる結果が得られるのかを検証する。
```js split-bill.js
const history = [
{
amount: 121,
payer: "A",
involves: ["A", "B", "C"],
},
{
amount: 98,
payer: "B",
involves: ["A", "B", "C"],
},
{
amount: 10,
payer: "C",
involves: ["A", "B", "C"],
},
{
amount: 10,
payer: "C",
involves: ["A", "B"],
},
{
amount: 50,
payer: "C",
involves: ["A"], // meaning C lent A 50
},
];
// calculate balance sheet
const init = { balance: 0, consumption: 0 };
Map.prototype.fetch = function (id) {
return (
this.get(id) || this.set(id, Object.assign({ name: id }, init)).get(id)
);
};
const data = new Map();
for (const { payer, amount, involves } of history) {
const record = data.fetch(payer);
record.balance += amount;
const debt = Math.ceil(amount / involves.length);
// actual payer should not owe extra debt coming from rounded up numbers
const payerDebt = amount - debt * (involves.length - 1);
for (const debtor of involves.map((i) => data.fetch(i))) {
const cost = Math.round(amount / involves.length);
debtor.balance -= cost;
debtor.consumption += cost;
}
}
console.log(data);
// calculate transaction table
const transaction = [];
let paidTooMuch, paidLess;
while (true) {
for (const [_, tbl] of data) {
if (tbl.balance >= (paidTooMuch?.balance || 0)) {
paidTooMuch = tbl;
}
if (tbl.balance <= (paidLess?.balance || 0)) {
paidLess = tbl;
}
}
if (paidLess.balance == 0 || paidTooMuch.balance == 0) break;
const amount = Math.min(paidTooMuch.balance, Math.abs(paidLess.balance));
transaction.push({
sender: paidLess.name,
receiver: paidTooMuch.name,
amount,
});
paidTooMuch.balance -= amount;
paidLess.balance += amount;
}
console.log("Settled");
console.log("\n# Transaction table");
for (const ev of transaction) {
console.log(`${ev.sender} owes ${ev.receiver} ¥${ev.amount}`);
}
console.log("\n# History");
for (const { payer, amount, involves } of history) {
if (involves.length === 1) {
console.log(`${payer} lent ¥${amount} to ${involves[0]}`);
} else {
console.log(`${payer} paid ¥${amount} for ${involves.join(", ")}`);
}
}
console.log("\n# Expenses");
for (const [_, { name, consumption }] of data) {
console.log(`${name} virtually paid ¥${consumption} in total`);
}
```
`history`に支払い履歴を書き込んで実行すると、「送金表」「履歴」「実質支払総額」が得られる。
```md
# Transaction table
A owes B ¥10
C owes B ¥6
# History
A paid ¥121 for A, B, C
B paid ¥98 for A, B, C
C paid ¥10 for A, B, C
C paid ¥10 for A, B
C lent ¥50 to A
# Expenses
A virtually paid ¥131 in total
B virtually paid ¥81 in total
C virtually paid ¥76 in total
```
プログラムに落とし込むことができたら、あとはスプレッドシートのマクロにするなり自由だ。面倒なことは全部コンピューターにやらせよう!

View File

@@ -0,0 +1,77 @@
---
title: 手のひらサイズのオイルランタン
date: 2021-06-08T00:00:00
---
UCO キャンドルランタンを改造して手のひらサイズのオイルランタンを作った。
![](lantern.jpeg)
# 特徴
- 手のひらサイズのオイルランタン
- ロウソクより大きい炎
- 暗所でもオイル残量が見やすい
- 揺らしてもオイルが漏れない
- 瓶を入れたまま仕舞える
# 材料
ほとんどのパーツはドラッグストアやホームセンターで調達できる。
1. 大正漢方胃腸薬(30 ml)
![](taisho.png)
2. C タイプアンカー M8(ステンレス)
3. 袋ナット M8(ステンレス)
4. ハードロックボルト M8(ステンレス)
5. [ゴムパッキン 直径 28x 内径 23x 厚さ 2mm](https://www.amazon.co.jp/gp/product/B003PHKRZS)(耐熱ではないけど今のところ耐えている)
6. [3mm グラスファイバー芯](https://www.amazon.co.jp/gp/product/B07X1VZFGB)
7. 隙間テープ(ダイソー)
# 手順
1. M8 アンカーのネジ部分を金属ノコギリで切断して断面をヤスリで整える
2. キャップに印字されているラベルをヤスリで削りとる(任意)
3. キャップの裏に張り付いている液漏れ防止シールを剥がす(熱で溶解するため)
4. キャップの内側からドリルで穴をあけ、棒やすりでネジが入るサイズまで広げる
5. ネジをキャップに差し込む
6. ゴムパッキンをキャップの裏にはめ込む
7. ハードロックボルトでネジの両側を固定する(レンチ等を使用して強く固定する)
8. 芯をボルトの中に通す(テープで芯の先を固定するとやりやすい)
9. 袋ネジで封をする
10. 切断した隙間テープをランタンの底面キャップに巻きつける
11. 瓶をランタンに差し込み底面キャップを締める
# 使用法
1. パラフィンオイルを 4/5 ほど入れてキャップを締め、オイルが芯の先に浸透するまで 15 分以上放置する
2. 芯の焦げている部分を 1mm 前後、それ以外の部分を 1mm ほど露出させてほぐす
3. 芯に火を付けてホヤを上げる
4. 使わないときはオイルを抜く(オイルが入ったままだと毛細管現象で染み出してくる)
## 🔥 燃焼時間
- 3-4cm の炎で 2-3 時間
- 最大 3 時間 47 分
![](lantern2.jpg)
# 製作メモ
## UCO キャンドルランタンの寸法 (mm)
| 筒の経 | 筒の長さ | 筒口(上) | 土台経 | キャップ内径 | 筒露出長 |
| ------ | -------- | ---------- | ------ | ------------ | -------- |
| 35.0 | 92.45 | 20.0 | 32.5 | 41.7 | 9.0 |
## やってみたい
- **内径が 18 ~ 21、太さが 2mm 程度**で耐油性のあるパッキンを試す
- M8 ボルトが通り、外径がガラス内径に近い低めの瓶を探す
- ガスケットで密封?
## 失敗例: M6 ボルトは微妙
ネットで広く紹介されている M6 ボルトを使う方法だと、炎がロウソク並に小さくなってしまった。あまりオススメできない。
![](comparison.jpeg)

Binary file not shown.

After

Width:  |  Height:  |  Size: 838 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Some files were not shown because too many files have changed in this diff Show More