Skip to main content

23 posts tagged with "Linux"

View all tags

Installing Rocky Linux 8.10 on WSL

Download Rocky Linux 8.10 Image

$dest = Join-Path $env:TEMP "Rocky-8-Container-Base.latest.x86_64.tar.xz"
Invoke-WebRequest -Uri "https://dl.rockylinux.org/pub/rocky/8/images/x86_64/Rocky-8-Container-Base.latest.x86_64.tar.xz" -OutFile $dest

Import

wsl --import RockyLinux-8.10 $HOME $dest

Install passwd

wsl -d RockyLinux-8.10 -u root dnf update -y `&`& dnf install -y passwd

Create a User

$username = "hikari" # Set your preferred username
wsl -d RockyLinux-8.10 -u root useradd -mG wheel $username
wsl -d RockyLinux-8.10 -u root passwd -d $username # Remove the user's password

Install sudo

wsl -d RockyLinux-8.10 -u root dnf update -y `&`& dnf install sudo -y

Set Default User

$username = "hikari" # Set your preferred username
$uid = wsl -d RockyLinux-8.10 id $username -u
if (-not $uid) {
Write-Error "Failed to get UID. User '$username' might not exist."
exit 1
}

$basePath = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Lxss"

$targetKey = Get-ChildItem $basePath | Where-Object {
(Get-ItemProperty $_.PSPath).DistributionName -eq "RockyLinux-8.10"
}
if (-not $targetKey) {
Write-Error "DistributionName 'RockyLinux-8.10' not found."
exit 1
}

Set-ItemProperty -Path $targetKey.PSPath -Name "DefaultUid" -Value ([int]$uid)

Enable EPEL

wsl -d RockyLinux-8.10 -u root dnf update -y `&`& dnf install -y epel-release

Start

wsl -d RockyLinux-8.10

To Make it the Default Distribution

wsl --set-default RockyLinux-8.10

Install FastFetch

wsl -d RockyLinux-8.10 -u root dnf update -y `&`& dnf install fastfetch

Run FastFetch

> wsl -d RockyLinux-8.10 -u root fastfetch
__wgliliiligw_, root@DESKTOP-MS-7C56-B550
_williiiiiiliilililw, -------------------------
_%iiiiiilililiiiiiiiiiii_ OS: Rocky Linux 8.10 x86_64
.Qliiiililiiiiiiililililiilm. Host: Windows Subsystem for Linux (2.0.14.0)
_iiiiiliiiiiililiiiiiiiiiiliil, Kernel: 5.15.133.1-microsoft-standard-WSL2
.lililiiilililiiiilililililiiiii, Uptime: 8 mins
_liiiiiiliiiiiiiliiiiiF{iiiiiilili, Packages: 285 (rpm)
jliililiiilililiiili@` ~ililiiiiiL Shell: bash 4.4.20
iiiliiiiliiiiiiili>` ~liililii Display 1: 1920x1080 @ 60Hz
liliiiliiilililii` -9liiiil Display 2: 1920x1080 @ 60Hz
iiiiiliiliiiiii~ "4lili WM: WSLg (Wayland)
4ililiiiiilil~| -w, )4lf Terminal: Windows Terminal
-liiiiililiF' _liig, )' CPU: AMD Ryzen 9 3900X (24) @ 3.800018 GHz
)iiiliii@` _QIililig, GPU: Microsoft Corporation Basic Render Driver
)iiii>` .Qliliiiililw Memory: 458.57 MiB / 62.76 GiB (0%)
)<>~ .mliiiiiliiiiiil, Disk (/): 51.72 GiB / 1007 GiB (5%)
_gllilililiililii~ Locale: C.UTF-8
giliiiiiiiiiiiiT`
-^~$ililili@~~' ████████████████████████
████████████████████████

Enable epel-release on RHEL 10.0

sudo dnf update -y
sudo subscription-manager repos --enable codeready-builder-for-rhel-10-x86_64-rpms
sudo dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-10.noarch.rpm

Using Official Rocky Linux Images on AWS

How to choose an AMI

Obtain the AMI from the official page.

https://rockylinux.org/ja-JP/download

Select the architecture for your instance (ARM (aarch64)) and choose AWS AMI under Cloud Images.

alt text

Filter by version number to find the appropriate one.

alt text

The AMI ID cannot be copied directly, so click the "Deploy" button and copy it from the AWS console.

Searching by AMI ID will show it.

alt text

It might be better to filter by owner.

Owner = 792107900819

alt text

Pre-requisites

  • Register a key pair
  • Run ssh-keygen -t ed25519 beforehand to create a public key, then import .ssh/id_ed25519.pub into your key pair.
  • Install AWS CLI
  • Install the CLI.
  • Configure access keys (aws configure).

Setting up the Network

An Elastic IP is cheaper than a NAT Gateway, so create an Elastic IP.

The network architecture looks like this:

Create an EC2 Instance Connect Endpoint

alt text

Creating an EC2 Instance Connect Endpoint allows you to log in from the AWS CLI.

Launching an Instance

  • Allow ICMP (Echo Request) to accept ping requests (Security Group).
  • Allow SSH connections (Security Group).
  • Mumbai region and arm64 instances are inexpensive.
  • Requires 1.5 GiB RAM per vCPU (at least t4g.medium).

Therefore, I launched an instance with the following conditions:

  • Region: Mumbai
  • Architecture: arm64
  • AMI: RHEL 8.10 (LVM, aarch64); ami-0415efd8380284dc4
  • Instance Type: t4g.medium
  • Key pair: Public key created on PC (.ssh/id_ed25519.pub)
  • Network: Public subnet (associated with a route table that defines a route to an internet gateway)
  • Security Group: Create a security group (default name)
  • SSH, 0.0.0.0/0
  • Custom ICMP - IPv4 (Echo request), 0.0.0.0/0
  • Storage: 1x 10GiB, gp3

Connection

Open your PC's terminal and run the following:

aws ec2-instance-connect ssh --private-key-file .ssh/id_ed25519 --os-user rocky --instance-id i-*****************

Install Instance Connect Package

The Rocky Linux AMI does not include the Instance Connect package, preventing connections from the Management Console. Therefore, the package must be installed.

Refer to https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/ec2-instance-connect-set-up.html for instructions on downloading the package.

  • Note: Select the RHEL package.
  • Note: It may not work correctly if the OS major version or architecture differs.

Example

curl https://amazon-ec2-instance-connect-us-west-2.s3.us-west-2.amazonaws.com/latest/linux_arm64/ec2-instance-connect.rhel8.rpm -o /tmp/ec2-instance-connect.rpm
curl https://amazon-ec2-instance-connect-us-west-2.s3.us-west-2.amazonaws.com/latest/linux_amd64/ec2-instance-connect-selinux.noarch.rpm -o /tmp/ec2-instance-connect-selinux.rpm
sudo dnf install -y /tmp/ec2-instance-connect.rpm /tmp/ec2-instance-connect-selinux.rpm

Once installed, you will be able to access the instance from the Management Console.

alt text

CDK (typescript)

I've included the CDK code I created for reference.

Remember to change the keyName (key pair) name.

import * as cdk from 'aws-cdk-lib';
import * as ec2 from 'aws-cdk-lib/aws-ec2';

export interface RockyLinuxStackProps extends cdk.StackProps {
}

export class RockyLinuxStack extends cdk.Stack {
public constructor(scope: cdk.App, id: string, props: RockyLinuxStackProps = {}) {
super(scope, id, props);

// Resources
const ec2dhcpOptions = new ec2.CfnDHCPOptions(this, 'EC2DHCPOptions', {
domainName: 'ap-south-1.compute.internal',
domainNameServers: [
'AmazonProvidedDNS',
],
],
});
ec2dhcpOptions.cfnOptions.deletionPolicy = cdk.CfnDeletionPolicy.DELETE;

const ec2InternetGateway = new ec2.CfnInternetGateway(this, 'EC2InternetGateway', {
{
value: 'igw',
key: 'Name',
},
],
});
ec2InternetGateway.cfnOptions.deletionPolicy = cdk.CfnDeletionPolicy.DELETE;

const ec2vpc = new ec2.CfnVPC(this, 'EC2VPC', {
cidrBlock: '10.0.0.0/16',
enableDnsSupport: true,
instanceTenancy: 'default',
enableDnsHostnames: true,
{
value: 'vpc',
key: 'Name',
},
],
});
ec2vpc.cfnOptions.deletionPolicy = cdk.CfnDeletionPolicy.DELETE;

const ec2VPCGatewayAttachment = new ec2.CfnVPCGatewayAttachment(this, 'EC2VPCGatewayAttachment', {
vpcId: ec2vpc.ref,
internetGatewayId: ec2InternetGateway.ref,
});
ec2VPCGatewayAttachment.cfnOptions.deletionPolicy = cdk.CfnDeletionPolicy.DELETE;

const ec2NetworkAcl = new ec2.CfnNetworkAcl(this, 'EC2NetworkAcl', {
vpcId: ec2vpc.ref,
],
});
ec2NetworkAcl.cfnOptions.deletionPolicy = cdk.CfnDeletionPolicy.DELETE;

const ec2RouteTable = new ec2.CfnRouteTable(this, 'EC2RouteTable', {
vpcId: ec2vpc.ref,
});
ec2RouteTable.cfnOptions.deletionPolicy = cdk.CfnDeletionPolicy.DELETE;

const ec2SecurityGroup = new ec2.CfnSecurityGroup(this, 'EC2SecurityGroup', {
groupDescription: 'launch-wizard-1 created 2025-04-27T00:11:58.641Z',
groupName: 'launch-wizard-1',
vpcId: ec2vpc.ref,
securityGroupIngress: [
{
cidrIp: '0.0.0.0/0',
ipProtocol: 'tcp',
fromPort: 22,
toPort: 22,
},
{
cidrIp: '0.0.0.0/0',
ipProtocol: 'icmp',
fromPort: 8,
toPort: -1,
},
],
securityGroupEgress: [
{
cidrIp: '0.0.0.0/0',
ipProtocol: '-1',
fromPort: -1,
toPort: -1,
},
],
});
ec2SecurityGroup.cfnOptions.deletionPolicy = cdk.CfnDeletionPolicy.DELETE;

const ec2Subnet = new ec2.CfnSubnet(this, 'EC2Subnet', {
vpcId: ec2vpc.ref,
mapPublicIpOnLaunch: false,
enableDns64: false,
availabilityZoneId: 'aps1-az1',
privateDnsNameOptionsOnLaunch: {
EnableResourceNameDnsARecord: false,
HostnameType: 'ip-name',
EnableResourceNameDnsAAAARecord: false,
},
cidrBlock: '10.0.0.0/20',
ipv6Native: false,
{
value: 'subnet-public1-ap-south-1a',
key: 'Name',
},
],
});
ec2Subnet.cfnOptions.deletionPolicy = cdk.CfnDeletionPolicy.DELETE;

const ec2InstanceConnectEndpoint = new ec2.CfnInstanceConnectEndpoint(this, 'EC2InstanceConnectEndpoint', {
preserveClientIp: false,
securityGroupIds: [
ec2SecurityGroup.attrGroupId,
],
subnetId: ec2Subnet.attrSubnetId,
});
ec2InstanceConnectEndpoint.cfnOptions.deletionPolicy = cdk.CfnDeletionPolicy.DELETE;

const ec2vpcdhcpOptionsAssociation = new ec2.CfnVPCDHCPOptionsAssociation(this, 'EC2VPCDHCPOptionsAssociation', {
vpcId: ec2vpc.ref,
dhcpOptionsId: ec2dhcpOptions.ref,
});
ec2vpcdhcpOptionsAssociation.cfnOptions.deletionPolicy = cdk.CfnDeletionPolicy.DELETE;

const ec2RouteHg = new ec2.CfnRoute(this, 'EC2RouteHG', {
routeTableId: ec2RouteTable.ref,
destinationCidrBlock: '0.0.0.0/0',
gatewayId: ec2InternetGateway.ref,
});
ec2RouteHg.cfnOptions.deletionPolicy = cdk.CfnDeletionPolicy.DELETE;

const ec2SubnetNetworkAclAssociation = new ec2.CfnSubnetNetworkAclAssociation(this, 'EC2SubnetNetworkAclAssociation', {
networkAclId: ec2NetworkAcl.ref,
subnetId: ec2Subnet.ref,
});
ec2SubnetNetworkAclAssociation.cfnOptions.deletionPolicy = cdk.CfnDeletionPolicy.DELETE;

const ec2SubnetRouteTableAssociation = new ec2.CfnSubnetRouteTableAssociation(this, 'EC2SubnetRouteTableAssociation', {
routeTableId: ec2RouteTable.ref,
subnetId: ec2Subnet.ref,
});
ec2SubnetRouteTableAssociation.cfnOptions.deletionPolicy = cdk.CfnDeletionPolicy.DELETE;

const ec2Instance = new ec2.CfnInstance(this, 'EC2Instance', {
tenancy: 'default',
instanceInitiatedShutdownBehavior: 'stop',
cpuOptions: {
threadsPerCore: 1,
coreCount: 2,
},
blockDeviceMappings: [
{
ebs: {
volumeType: 'gp3',
iops: 3000,
volumeSize: 10,
encrypted: false,
deleteOnTermination: true,
},
deviceName: '/dev/sda1',
},
],
availabilityZone: 'ap-south-1a',
privateDnsNameOptions: {
enableResourceNameDnsARecord: false,
hostnameType: 'ip-name',
enableResourceNameDnsAaaaRecord: false,
},
ebsOptimized: true,
disableApiTermination: false,
keyName: 'hikari',
sourceDestCheck: true,
placementGroupName: '',
networkInterfaces: [
{
privateIpAddresses: [
{
privateIpAddress: '10.0.3.59',
primary: true,
},
],
secondaryPrivateIpAddressCount: 0,
deviceIndex: '0',
groupSet: [
ec2SecurityGroup.ref,
],
ipv6Addresses: [
],
subnetId: ec2Subnet.ref,
associatePublicIpAddress: true,
deleteOnTermination: true,
},
],
imageId: 'ami-0415efd8380284dc4',
instanceType: 't4g.medium',
monitoring: false,
],
creditSpecification: {
cpuCredits: 'unlimited',
},
});
ec2Instance.cfnOptions.deletionPolicy = cdk.CfnDeletionPolicy.DELETE;

const ec2ElasticIp = new ec2.CfnEIP(this, 'EC2ElasticIp', {
domain: 'vpc',
{
key: 'Name',
value: 'elastic-ip',
},
],
});
ec2ElasticIp.cfnOptions.deletionPolicy = cdk.CfnDeletionPolicy.DELETE;

const ec2EipAssociation = new ec2.CfnEIPAssociation(this, 'EC2EipAssociation', {
eip: ec2ElasticIp.ref,
instanceId: ec2Instance.ref,
});
ec2EipAssociation.cfnOptions.deletionPolicy = cdk.CfnDeletionPolicy.DELETE;
}
}

How to Connect to Ubuntu in Hyper-V via Serial Console

VM Settings

Select "Named pipe" and set the pipe name to "COM1".

Hyper-V Serial Settings

Ubuntu Settings

GRUB Settings

Open the GRUB configuration file with sudo nano /etc/default/grub.

GRUB_CMDLINE_LINUX_DEFAULT="quiet splash console=ttyS0,115200n8"

After saving, apply the GRUB settings with:

sudo update-grub

Enable Serial Port

Configure the service to allow login via the serial port.

sudo systemctl enable [email protected]
sudo systemctl start [email protected]

Connection

Launch as administrator.

Connect from Tera Term

Connect Serial port of Ubuntu on Hyper-V from Tera Term

Connect from PuTTY

Launch as administrator.

Serial lineSpeedConnection type:
\.\pipe\COM1115200Serial

Set the above.

Connect Serial port of Ubuntu on Hyper-V from PuTTy

Connect Serial port of Ubuntu on Hyper-V from PuTTy

Launch as administrator.

Connect Serial port of Ubuntu on Hyper-V from plink.exe on WindowsTerminal

[System.Console]::OutputEncoding = [System.Text.Encoding]::GetEncoding("utf-8")
[System.Console]::InputEncoding = [System.Text.Encoding]::GetEncoding("utf-8")
plink.exe -serial \\.\pipe\COM1 -sercfg 115200,8,n,1,N

Exit with Ctrl + C.

Linux Network Management Commands (nmcli and nmtui)

nmcli

nmcli connection: Display all connections

pi@raspberrypi:~ $ nmcli connection
NAME UUID TYPE DEVICE
preconfigured 1b29633c-51a7-42a8-8357-a23ddbb791b9 wifi wlan0
lo 37334688-5c87-47fc-87d3-8c4e31934dd2 loopback lo
有線接続 1 0df9157e-b1a9-3026-9bd5-f05234e1cf4b ethernet --

nmcli device: Display devices and their states

pi@raspberrypi:~ $ nmcli device
DEVICE TYPE STATE CONNECTION
wlan0 wifi 接続済み preconfigured
lo loopback 接続済み (外部) lo
p2p-dev-wlan0 wifi-p2p 切断済み --
eth0 ethernet 利用不可 --

nmcli connection show ...: Display properties

Run nmcli connection show <profile name> to display its properties.

pi@raspberrypi:~ $ nmcli connection show <プロファイル名>
connection.id: <プロファイル名>
connection.uuid: 1b29633c-51a7-42a8-8357-a23ddbb791b9
connection.stable-id: --
connection.type: 802-11-wireless
connection.interface-name: --
connection.autoconnect: はい
connection.autoconnect-priority: 0
connection.autoconnect-retries: -1 (default)
connection.multi-connect: 0 (default)
connection.auth-retries: -1
connection.timestamp: 1710955164
connection.read-only: いいえ
connection.permissions: --
connection.zone: --
connection.master: --
connection.slave-type: --
connection.autoconnect-slaves: -1 (default)
connection.secondaries: --
connection.gateway-ping-timeout: 0
connection.metered: 不明
connection.lldp: default
connection.mdns: -1 (default)
connection.llmnr: -1 (default)
connection.dns-over-tls: -1 (default)
lines 1-24

Check IP address

pi@raspberrypi:~ $ nmcli connection show <プロファイル名> | grep ipv4.addresses
ipv4.addresses: 192.168.10.113/24

Set IP address

In the example below, the IP address is set to 192.168.10.113 and the prefix length to 24.

sudo nmcli connection modify <プロファイル名> ipv4.addresses 192.168.10.113/24

Check DNS server

pi@raspberrypi:~ $ nmcli connection show <プロファイル名> | grep ipv4.dns:
ipv4.dns: 192.168.10.1

Set DNS server

In the example below, the DNS server is set to 192.168.10.1.

sudo nmcli connection modify <プロファイル名> ipv4.dns 192.168.10.1

Disconnect a connection

sudo nmcli connection down <プロファイル名>

Connect a connection

sudo nmcli connection up <プロファイル名>

nmtui: Configure network connections with TUI

sudo nmtui

How to Japanese the Linux Prompt

This post introduces how to Japanese the Linux prompt.

1. Install Japanese Locale

Next, if the Japanese locale does not exist, install it with the following command.

sudo apt update
sudo apt install language-pack-ja

2. Set the Locale

Set the Japanese locale with the following command.

sudo update-locale LANG=ja_JP.UTF8

3. Restart the System

Finally, restart the system. This will reflect the new locale settings.

sudo reboot

With the above steps, the Linux prompt will be Japanese.

How to install pyenv and Python on Ubuntu (including WSL2)

Install Dependencies

Reference: Home · pyenv/pyenv Wiki

sudo apt update
sudo apt install build-essential libssl-dev zlib1g-dev \
libbz2-dev libreadline-dev libsqlite3-dev curl \
libncursesw5-dev xz-utils tk-dev libxml2-dev libxmlsec1-dev libffi-dev lbmzma-dev

Install pyenv

Reference: [pyenv/pyenv-installer: This tool is used to install pyenv and friends.] (https://github.com/pyenv/pyenv-installer?tab=readme-ov-file)

curl https://pyenv.run | bash

Add initialization script to ~/.bashrc

# Open ~/.bashrc
code ~/.bashrc

Add the following:

export PYENV_ROOT="$HOME/.pyenv"
[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"

eval "$(pyenv virtualenv-init -)"

Install Python

Display a list of installable versions

pyenv install -l

Install Python

Install Python 3.12.2.

pyenv install 3.12.2

Set the Python version

Set the default version to Python 3.12.2.

pyenv global 3.12.2

python -V # Python 3.12.2

How to install .NET on Ubuntu (including WSL2)

Reference: Install .NET on Linux without using a package manager - .NET | Microsoft Learn

Download the install script

wget https://dot.net/v1/dotnet-install.sh -O dotnet-install.sh

Make the install script executable

chmod +x ./dotnet-install.sh

Install the dot.net SDK

./dotnet-install.sh

To install the latest version

./dotnet-install.sh --version latest

Add to path

Open $HOME/.bashrc and add the following:

export DOTNET_ROOT=$HOME/.dotnet
export PATH=$PATH:$DOTNET_ROOT:$DOTNET_ROOT/tools

Installation Guide for rbenv (WSL2 / Ubuntu)

Installing Dependencies

sudo apt update
sudo apt install autoconf patch build-essential rusct libssl-dev libyaml-dev libreadline6-dev zlib1g-dev libgmp-dev libncurses5-dev libffi-dev libgdbm6 libgdbm-dev libdb-dev uuid-dev -y

Installing rbenv

# Install rbenv and ruby-build
curl -fsSL https://github.com/rbenv/rbenv-installer/raw/HEAD/bin/rbenv-installer | bash

# Initialize rbenv on startup
echo 'eval "$($HOME/.rbenv/bin/rbenv init - bash)"' | tee -a ~/.bashrc

Reference

Installing Ruby 3.3.0

source ~/.bashrc # Initialize rbenv (can also be done after re-logging into WSL)
rbenv install 3.3.0 # Install Ruby 3.3.0
rbenv global 3.3.0 # Set Ruby 3.3.0 as the default

Reference

Installing Docker on Ubuntu

This is a translation of the Docker installation guide for Ubuntu.

[EOL]

  1. Installing Docker Engine

    • Using Package Manager: This is the recommended method for most users.

      sudo apt-get update
      sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin
    • Using the Convenient Script: Docker provides a convenient script for quickly and non-interactively installing Docker in development environments. While not recommended for production, it can be useful for creating provisioning scripts tailored to your needs. Refer to the install using package repository instructions for installation steps using the repository. The script's source code is open source and available on the GitHub docker-install repository. Always review downloaded scripts before executing them.

      curl -fsSL https://get.docker.com -o get-docker.sh
      sudo sh get-docker.sh
    • Using Pre-release: Docker also provides a convenient script to install pre-releases of Docker on Linux, available at test.docker.com. This script configures the package manager to enable the "test" channel from which you can access early versions of new releases and test them in a non-production environment before they are released as stable.

      curl -fsSL https://test.docker.com -o test-docker.sh
      sudo sh test-docker.sh
    • Important: Before running the script, it's a good practice to preview the steps the script will execute by using the DRY_RUN=1 option.

      curl -fsSL https://get.docker.com -o get-docker.sh
      DRY_RUN=1 sh ./get-docker.sh
  2. Post-Installation Steps

  3. Uninstalling Docker Engine

    • Uninstalling Packages:

      sudo apt-get purge docker-ce docker-ce-cli containerd.io docker-compose-plugin
    • Removing Images, Containers, and Volumes: The above command does not automatically remove images, containers, or volumes on the host. To remove all images, containers, and volumes, use the following commands:

      sudo rm -rf /var/lib/docker
      sudo rm -rf /var/lib/containerd
    • Manual Removal: Any manually created configuration files must be removed manually.

  4. Next Steps