What is /proc in Linux (for beginners)

What is /proc

There is a directory named /proc on Linux. The files in this directory are virtual, for the Linux kernel to provide internal information; there is no file entity anywhere, like files on an SSD.

Example of files in /proc

An example is as follows. The ls command is executed with -F option, directories and symbolic links are respectively shown with / and @ at the tail.
$ ls -F /proc/
1/      73669/     crypto          irq/         modules       sys/
3674/   73681/     devices         kallsyms     mounts@       sysrq-trigger
3675/   73687/     diskstats       kcore        mtrr          sysvipc/
38/     91/        dma             keys         net@          thread-self@
4771/   92/        driver/         key-users    pagetypeinfo  timer_list
4777/   acpi/      dynamic_debug/  kmsg         partitions    tty/
4778/   asound/    execdomains     kpagecgroup  pressure/     uptime
61/     buddyinfo  fb              kpagecount   schedstat     version
72/     bus/       filesystems     kpageflags   self@         vmallocinfo
73/     cgroups    fs/             loadavg      slabinfo      vmstat
73632/  cmdline    interrupts      locks        softirqs      zoneinfo
73638/  consoles   iomem           meminfo      stat
73639/  cpuinfo    ioports         misc         swaps
As you can see at first glance, there are directories with only numbers (e.g. 1/, 3674/, etc.) and other files and directories (e.g. acpi/, buddyinfo, etc.). Numeric directories contain information on processes with process numbers of that value in the form of files under that directory. Other files and directories (files included in) contain information about the entire system.

Directories for process

Now, as an example, let's run the sleep command and start the process. The process is started with process ID 73717.
$ sleep 3600 &
[1] 73717
Let's look at the /proc information about this process.
$ ls -F /proc/73717/
arch_status         fd/                net/           setgroups
attr/               fdinfo/            ns/            smaps
autogroup           gid_map            numa_maps      smaps_rollup
auxv                io                 oom_adj        stack
cgroup              ksm_merging_pages  oom_score      stat
clear_refs          ksm_stat           oom_score_adj  statm
cmdline             limits             pagemap        status
comm                loginuid           patch_state    syscall
coredump_filter     map_files/         personality    task/
cpu_resctrl_groups  maps               projid_map     timens_offsets
cpuset              mem                root@          timers
cwd@                mountinfo          sched          timerslack_ns
environ             mounts             schedstat      uid_map
exe@                mountstats         sessionid      wchan
There are many different files and directories, but I will list here two that I often use.

exe

Here is a link to the executable of the process. You can see that the executable of the process is /usr/bin/sleep.
 $ ls -l /proc/73717/exe
lrwxrwxrwx 1 foo foo 0 Mar 19 11:06 /proc/73717/exe -> /usr/bin/sleep

fd

It contains a symbolic link to the file that the process is opening. The file name of the symbolic link is the descriptor number. In this case, we see that three files for standard I/O are open.
$ ls -l /proc/73717/fd
total 0
lrwx------ 1 foo foo 64 Mar 19 11:15 0 -> /dev/pts/5
lrwx------ 1 foo foo 64 Mar 19 11:15 1 -> /dev/pts/5
lrwx------ 1 foo foo 64 Mar 19 11:15 2 -> /dev/pts/5

Entire system information

Three system-wide files are also presented.

partitions

Partitions detected by the Linux kernel are included. In the following, the NVMe storage partition is shown. When a USB storage device is inserted, sda, sda1, sda2, etc. will be added to the list. This is useful to check if the Linux kernel recognizes the connected storage device.
$ cat /proc/partitions 
major minor  #blocks  name

 259        0 1953514584 nvme0n1
 259        1     498688 nvme0n1p1
 259        2   19530752 nvme0n1p2
 259        3   19530752 nvme0n1p3
 259        4   19530752 nvme0n1p4
 259        5   19530752 nvme0n1p5
 259        6 1874891776 nvme0n1p6

uptime

The time since Linux was started is stored.
$ uptime
 11:22:23 up  9:19,  2 users,  load average: 0.00, 0.00, 0.00

self

When a process refers to this file, it is a link to the directory for that process. In other words, different links point to different destinations depending on the process reading them.

In the following example, The link 73729 is the directory for the ls command itself which is reading /proc.

$ ls -l /proc/self
lrwxrwxrwx 1 root root 0 Mar 19 02:02 /proc/self -> 73729

More information

There are many files in /proc as shown in the examples in this article. See below for a detailed description of them.

How to build a Linux kernel

This article shows you how to build a Linux kernel, which is useful for using features supported only in the latest kernels from the Linux community or for creating your own Linux OS. The commands listed here have been verified to run on Debian 11, but are basically the same for other Linux operating systems (except for how to install packages).

Preparation to build

Install the following packages.
sudo apt install gcc make flex bison bc libncurses-dev libelf-dev libssl-dev

Get a kernel source code

Linux kernel source code can be downloaded from the following site.

The latest stable version on the day this post was written was6.2.7. The following shows an example of downloading it to a working directory on a build machine.
wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.2.7.tar.xz

Build

Extract the source code

tar xf linux-6.2.7.tar.xz

Configuration

ここではデフォルト設定を行います。
cd linux-6.2.7
make defconfig

When more configuration is required

make menuconfig
After entering the above, the following TUI-based configuration screen will appear. This can be used to add/remove the required CONFIGs.

Compile

make -j32

The above -j32 is an option to compile in 32 parallel. It should be changed accordingly to the actual number of CPUs.

If the following message appears, the build was successful. The following bzImage is the same as the named like vmlinuz-6.1.0-5-amd64 in many Linux OS.

Kernel: arch/x86/boot/bzImage is ready  (#1)

Launch test

Here we will use a Debian 11 drive image as a rootfs and boot with QEMU.

Download of a rootfs drive image

Download the rootfs image as follows.
wget https://cloud.debian.org/images/cloud/bullseye/20230124-1270/debian-11-nocloud-amd64-20230124-1270.qcow2

Launch

Run QEMU as follows. --nographic option is given so that a serial device is created in the virtual machine. The kernel option console=ttyS0 makes the serial device become a console. These make the terminal running QEMU the input/output terminal to the serial device as it is.

Note that when configured with defconfig, the virtio storage functionality is built into the kernel. The kernel can mount rootfs directly without initrd.

sudo qemu-system-x86_64 \
-cpu host \
--enable-kvm \
-m 1024 \
-nographic \
-drive id=drive0,format=qcow2,file=debian-11-nocloud-amd64-20230124-1270.qcow2,if=virtio \
-kernel arch/x86_64/boot/bzImage \
-append "root=/dev/vda1 console=ttyS0"
If the following login prompt appears, you have succeeded.
(abbr.)
Debian GNU/Linux 11 debian ttyS0

debian login:
This image allows to log in without password by use root as a user name.
Linux debian 6.2.7 #1 SMP PREEMPT_DYNAMIC Sun Mar 19 02:39:21 UTC 2023 x86_64
(abbr.)
root@debian:~#

How to force terminate QEMU when a launch fails

While QEMU is running, enter Ctrl-a followed by c to go to the QEMU monitor screen. Enter q here.
(Enter Ctrl-a, c)
QEMU 7.2.0 monitor - type 'help' for more information
(qemu) q

How to get the Web contents though a remote site with SOCKS proxy by ssh

Abstract

As shown in the figure below, when My Site cannot connect to Web Server X directly, but can connect via a remote SSH server (remote_server) that can be connected via SSH, this post explains how to get WebServer X pages in My Site's Web browser.

As a remote_server, AWS and Azure can be available. In that case, the region of the request source can be set to that of the data center.

Create a SOCKS proxy

Run the following command with a SSH client on My Site. This creates a SOCKS proxy and has HTTP requests being sent from remote_server. The port number 8080 can be changed.
ssh -D 8080 remote_server

Configuration of Web browser

Configure a SOCK proxy in your Web browser. When the SSH client is executed in localhost (the same machine), set the address like below.

Chrome

google-chrome --proxy-server="socks://localhost:8080"

Firefox

Proxy setting dialog will be shown as you follow Menu -> Settings -> Network Settings -> Settings...
Set the IP adddress and port in the dialog.

How to create a MySQL database on a memory (tmps)

Chgage datadir in /etc/mysql/my.conf to the directory on a tmpfs.
-datadir                = /var/lib/mysql
+datadir                = /dev/shm/mysql
Run the following command to create a DB on a new directory.
# mysql_install_db
Then, launch mysqld.
/etc/init.d/mysqld start

Note

The file created by mysql_install_db will be removed after reboot, so it may be a good idea to write the above setting in /etc/init.d/mysqld to be executed at the beginning. In some cases, such as Ubuntu, access may be restricted by apparmor. In that case, add the following description to /etc/apparmor.d/usr.sbin.mysqld.
  /dev/shm/mysql/** rwk,

An example to unbind/bind a USB device on Linux

# cd /sys/bus/usb/drivers/usb
# echo -n '2-1.6' > unbind; echo -n '2-1.6' > bind
The above 2-1.6 is a bus number. It changes by environment. You can find the device corresponding to the bus number as below.
# cat 2-1.6/manufacturer
RATOC Systems,Inc.
# cat 2-1.6/product
RAL-2496UT1 USB-Transport

A way to address the problem when 'X11 forwarding request failed on channel 0' is shown and X11 forwarding isn't working in ssh

Let's investigate the root case. You can show details by adding '-v' option to ssh. When No auth program is shown as below, you should install xauth by apt or yum.
...
debug1: Remote: No xauth program; cannot forward with spoofing.
X11 forwarding request failed on channel 0

Run Python script in GDB

Recent GDB (at least afeter version 7) can run Python script. To run it, we use source command as same as the GDB macro.

Let's try it. We prepare the following Python script.
$ cat hello.py
#!/usr/bin/env python
import sys
sys.stdout.write('Hello, my first script.\n')
Launch GDB and run the script
(gdb) source hello.py
Hello, my first script.

Use of GDB functions from a Python script

The following is the example to use GDB functions from a Python script. gdb.execute() can run operations used in the GDB command line.

The following example uses target.cc as a debug target.
[target.cc]
#include <cstdio>
#include <cstdlib>
#include <time.h>

int getval(int div)
{
        return time(NULL) / div;
}

int main(void)
{
        printf("val: %d\n", getval(5));
        return EXIT_SUCCESS;
}
show-bt.py will perform the following 4 operations.
  • Set a break point at the head of getval() function
  • Run the program
  • Show the bracktrace at the break point
  • Show rax register at the break point
[show-bt.py] 
gdb.execute('b getval')
gdb.execute('run')
gdb.execute('bt')
gdb.execute('p/x $rax')
The following is an example to run a script in the command line. The command line argument '-q' disables to show startup messages of GDB such as copyright. '-x' specifies the script to be executed.
$ gdb -q -x show-bt.py  target
Reading symbols from /home/foo/target...done.
Breakpoint 1 at 0x400627: file target.cc, line 7.

Breakpoint 1, getval (div=5) at target.cc:7
7               return time(NULL) / div;
#0  getval (div=5) at target.cc:7
#1  0x0000000000400656 in main () at target.cc:12
#2  0x00007ffff72d2ead in __libc_start_main (main=, argc=, ubp_av=, init=, fini=, rtld_fini=, stack_end=0x7fffffffe128) at libc-start.c:228
#3  0x0000000000400539 in _start ()
$1 = 0x7ffff763aee8

Get output of a command as a Python string

The above example only executes normal GDB commands. Let's get the output as a Python string. It can be achived by passing True to to_string parameter of get.execute() function. Python is also good at string processing, so you can easily extract and display specific strings in a formatted format.

The following exmaple shows the frame number and the last word from the stacktrace.
$ cat show-bt-and-format.py 
gdb.execute('b getval')
gdb.execute('run')
bt = gdb.execute('bt', to_string=True)
for line in bt.split('\n'):
  words = line.split(' ')
  print '%s %s' % (words[0], words[-1])
$ gdb -q -x show-bt-and-format.py  target
Reading symbols from /home/foo/target...done.
Breakpoint 1 at 0x400627: file target.cc, line 7.

Breakpoint 1, getval (div=5) at target.cc:7
7               return time(NULL) / div;
#0 target.cc:7
#1 target.cc:12
#2 libc-start.c:228
#3 ()

Show a memory map of the process being attached by GDB

You can show a memory map of a program being attached by info proc map. The following illustrates an example with 'cat' command.

'cat' command w/o arguments continue to wait for standard input. To operate GDB in that case, CTRL + C is typed in the following.

$ gdb /bin/cat
[skip]
(gdb) run
Starting program: /bin/cat 
^C <= Interrupt by typing CTRL + C
Program received signal SIGINT, Interrupt.
0x00007ffff7afe6a0 in __read_nocancel () at ../sysdeps/unix/syscall-template.S:81
81      ../sysdeps/unix/syscall-template.S: No such file or directory.
(gdb) info proc map
process 31692
Mapped address spaces:

          Start Addr           End Addr       Size     Offset objfile
            0x400000           0x40b000     0xb000        0x0 /bin/cat
            0x60a000           0x60b000     0x1000     0xa000 /bin/cat
            0x60b000           0x60c000     0x1000     0xb000 /bin/cat
            0x60c000           0x62d000    0x21000        0x0 [heap]
      0x7ffff7a12000     0x7ffff7bcf000   0x1bd000        0x0 /lib/x86_64-linux-gnu/libc-2.17.so
      0x7ffff7bcf000     0x7ffff7dcf000   0x200000   0x1bd000 /lib/x86_64-linux-gnu/libc-2.17.so
      0x7ffff7dcf000     0x7ffff7dd3000     0x4000   0x1bd000 /lib/x86_64-linux-gnu/libc-2.17.so
      0x7ffff7dd3000     0x7ffff7dd5000     0x2000   0x1c1000 /lib/x86_64-linux-gnu/libc-2.17.so
      0x7ffff7dd5000     0x7ffff7dda000     0x5000        0x0 
      0x7ffff7dda000     0x7ffff7dfd000    0x23000        0x0 /lib/x86_64-linux-gnu/ld-2.17.so
      0x7ffff7fcc000     0x7ffff7fcf000     0x3000        0x0 
      0x7ffff7ff8000     0x7ffff7ffa000     0x2000        0x0 
      0x7ffff7ffa000     0x7ffff7ffc000     0x2000        0x0 [vdso]
      0x7ffff7ffc000     0x7ffff7ffd000     0x1000    0x22000 /lib/x86_64-linux-gnu/ld-2.17.so
      0x7ffff7ffd000     0x7ffff7fff000     0x2000    0x23000 /lib/x86_64-linux-gnu/ld-2.17.so
      0x7ffffffde000     0x7ffffffff000    0x21000        0x0 [stack]
  0xffffffffff600000 0xffffffffff601000     0x1000        0x0 [vsyscall]
There is a similar command info shared. This only shows mapped shared libraries. The column 'Syms Read' indicates whethere the debug symbols has been read.
(gdb) info shared
From                To                  Syms Read   Shared Object Library
0x00007ffff7ddaaa0  0x00007ffff7df5439  Yes         /lib64/ld-linux-x86-64.so.2
0x00007ffff7a313c0  0x00007ffff7b7c39f  Yes         /lib/x86_64-linux-gnu/libc.so.6

Force to assign a terminal in ssh

If you use ssh in a script and try to give commands from standard input, you may get the following error.
Pseudo-terminal will not be allocated because stdin is not a terminal.
In such a case, specifying two -t's (i.e. 'ssh -t -t ...') solves the problem. -tt also works.

Note that if the input side has a terminal (i.e., the input is done manually at the terminal), only one -t need be specified.

Change the memory unit to MiB or GiB in top command

In Ubuntu and Debian, top command's default unit of memory usage (VIRT and RSS) is KiB. Recent applications use a lot of memory, so sometimes it is difficult to see many digits. In such cases, you can change the unit by pressing the following key.
  • E (uppercase):Change overall memory usage units at top
  • e (lowercase):Change the unit of memory usage for each app
The following screen capture is an example of overall memory usage at the top in GiB and memory usage for each app in MiB.

How to look at output of top command

The following screen will be shown by default (of Debian 12). This post describes the important three information surrounded by the red boxes.

(1) CPU execution time

The percentage of each execution type is displayed here, with the sum of all CPUs as 100%.
Type Description
us Execution time in user mode. Time for normal processing of the program.
sy Program execution time in kernel mode. The time that code in the kernel is executed when a program calls a system call. (This corresponds to reading and writing files, network processing, etc.)
ni Program execution time for processes with positive NICE values and low priority
id Idle time. Time when nothing is running.
wa Time spent waiting for a response from a device. E.g. an input/output process to a device such as storage.
hi Execution time of hardware interrupt processing
si Execution time of software interrupt processing
st Time a virtual CPU on a hypervisor-type virtual machine waits for physical CPU allocation

(2) Memory usage

Shows the total amount of memory used by the OS. The default unit is MiB.
Group Item Description
Mem total Total memory size
free Free memory size
used Used memory size
buff/cache Cache space size for directory entries and file contents; Linux actively allocates free memory to these caches, so these values tend to increase as free memory decreases with use.
Swap total Total swap size
free Free swap size
used Used swap size
avail Mem Available memory size. Roughly speaking, sum of the free memory size and the cache size.

(3) Each process status

The following table sumarizes the meaning of each column of the header. Processes are shown in descending order by default. The default unit of memory related items is KiB.  
Item Description
PID Process ID
USER The executioni user of the process
PR Execution priority of the process. The normal is 20. The smaller the number, the higher the priority.
NI NICE value. When this value is positive, it is executed at a low priority according to its value. When it is negative, it is executed at a high priority according to its value.
VIRT Virtual memory usage. Amount of memory allocated by the process. Only a portion of this value is allocated to physical memory. Even if this value is large, not much memory may be used.
RES Physical memory usage. Amount of physical memory allocated to the process. Actual memory usage for the process.
SHR Shared memory usage, the amount of memory in the RES that is shared with other processes.
S Process state: R (running), S (sleep), D (uninterruptible sleep), Z (zombie state)
%CPU CPU utilization. 100% when one CPU is fully used. This value may exceed 100% when multiple CPUs are used.
%MEM Memory utilization
TIME+ CPU usage time of the process. The total time that the CPU has been allocated (i.e., the process's program has been executed), not the time since it was started, in units of 1/100th of a second.
Example: 1:23.45 means 1 minute 23 seconds 450 milliseconds
COMMAND Exection command

What to do when 'X11 forwarding request failed on channel 0' is displayed and X11 forwarding cannot be done via ssh

Add the -v option to ssh to see the details and find the cause. If it says there is 'No auth program' as shown below, just install xauth with apt or yum.
...
debug1: Remote: No xauth program; cannot forward with spoofing.
X11 forwarding request failed on channel 0

How to create a packet capture file with tcpdump that Wireshark can analyze

Example

tcpdump -n -s 0 -i eth0 -w dump.dat
Blue characters part should be changed appropriately.

Explanation of options

Option Description
-n Show IP address (Don't use DNS)
-s 0 Makes a packet size for capture unlimited
-i Specifies the capture target network device
-w Specifies the capture file name to be created

How to show vlan tag with tcpdump

Add -e option.

Example

tcpdump -i eth0 -e icmp
Ethernet header information will be shown as the red line in the following figure. The valn tag is surrounded by the red rectangle.

Set the DNS server on Debian 11

Add dns-nameservers line in /etc/network/interfaces as below.
auto enp6s0
iface enp6s0 inet static
  bridge_ports enp6s0
  address 192.168.1.100
  netmask 255.255.255.0
  gateway 192.168.1.1
  dns-nameservers 192.168.1.254
Ref.: https://wiki.debian.org/NetworkConfiguration

Use a Web Browser as a VNC client

This article provides the procedures with the network of the following figure and the OS is Ubuntu 20.04.

Preparation and Run

Run the following commands on noVNC Server.

Download noVNC

git clone https://github.com/novnc/noVNC.git

When websockify is not installed, install it

sudo apt install python3-websockify

Run websockify

The right hand side of --web= is supposed to be a directory where noVNC is donwloaded. The next option is a port nubmer for a Web Browsers. The last option is an IP address and the port number of VNC server.
websockify --web=noVNC 8081 192.168.1.20:5901

Access from a Web Browser

Access the following 
  • http://192.168.1.10:8081/vnc.html


The following content will be shown in the browser.

Performance comparision among programming laguages

I created a program with single-thread simple algorithm that calculates prime numbers up to 100 million. I measured the execution time and the maximum used memory size. The source code is here.
Lang. Time (sec) Maximum used physical memory (MiB) Container for calculated prime numbers Remarks My impression
C 12.6 24.1 Fixed size array gcc 8.3.0
Optimization -O3
-
C++ 64.8 36.0 std::vector gcc 7.3.0
No optimization (build with -O0)
-
C++ 12.7 36.0 std::vector gcc 7.3.0
Optimization (build with -O3)
Optimzation is very effective. Memory usage is also less.
JAVA 17.2 215.5 ArrayList OpenJDK 10.0.2 Execution time about 1.5 times longer than C/C++. Roughly consistent with previous experience.
Kotlin 17.2 236.5 List Kotlin 1.3.61 Equivalent to Java. Not a bad choice considering the ease of writing code.
Scala 20.1 2023.0 mutable.ArrayBuffer Scala 2.11.12 In terms of speed, it is only slightly inferior to Java, but its memory usage is about 10 times that of Java and nearly 100 times that of C++.
Golang 49.2 136.2 slice go1.11.6 It is not faster than I expected. The memory usage is also about half that of Java, so this result alone may not be enough to make it halfway useful.
Node.js 23.2 184.8 Array v8.10.0 Comparable to Java and Scala. Faster than expected. Not too much memory usage.
PHP 151.2 196.7 array PHP 7.2.10 There doesn't seem to be anything particularly good about it. I don't think it's a language that I would force myself to use.
Python 451.8 3235.2 list 2.7 Very slow and memory usage is so bad. But I don't hate. I really should use NumPy or something like that for this kind of use. I'd like to try it with numba at a later date.
Python3 592.8 238.3 list 3.6.7 Memory usage is one half of that of Python2. However, the performance degraded.

How to paste a string into command line in Vim

After a yank is done, do the following operation.
CTRL-r " (double quote)

Example network setting for Debian 11 (server) with bridge

Example

The following is an example of /etc/network/interfaces. It configure a bridge br0 with a physical NIC enp6s0.
# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).

source /etc/network/interfaces.d/*

# The loopback network interface
auto lo
iface lo inet loopback

# The primary network interface
allow-hotplug enp6s0
iface enp6s0 inet manual

auto br0
iface br0 inet static
  bridge_ports enp6s0
  address 192.168.10.12
  netmask 255.255.255.0
  gateway 192.168.10.1
  dns-nameservers 192.168.10.1
  bridge_stp off
  bridge_maxwait 0

Note

The above setting requires 'bridge-utils' package.

Advantege of using a bridge

Adding a physical NIC to the bridge allows LXC containers and QEMU instances to easily connect to the network to which the host machine belongs. With macvlan and macvtap, there is an issue where the host OS and virtual machine cannot communicate, but this method can solve that.

Launch SSH server for root with password authentication (on a temporary basis)

Many of the recent Linux distro. disallows the root login with a password by default. The following command launches an SSH server on a temporary basis that allows the root login with a password.
/usr/bin/sshd -d -p 8022 -o "PermitRootLogin yes"
  • -d: Run on the foreground and show some debug messages.
  • -p: Port number
  • -o: Options. Here we allow root login.

A way to login from client.
ssh -p 8022 -lroot server-ip-addr

Expand a btrfs partion size on a loopback device

Expand the source loopback file (Change of and seek in the right hand side)
dd if=/dev/zero of=file_name.img bs=1 count=0 seek=100G
Update the size of the loopback device (Change the loopback device name at the tail as appropriate)
losetup -c /dev/loop3
Expand the btrfs (Change the mount point at the tail as appropriate)
btrfs filesystem resize max /mnt/mount_point

A way to solve a problem when firmware-nvidia-gsp 525.85.12 is missing on Debian.

This version firmware-nvidia-gsp is contained in non-free-firmware repository. So the following line should be added in (for example) /etc/apt/sources.list.
deb http://deb.debian.org/debian/ bookworm contrib non-free non-free-firmware

I like LXC than LXD for a simple use.

Roughly speaking, LXD is an enhanced version of LXC with management functions to make it easier to use for large-scale operations. When used by individuals as a simple virtual machine, the functions of LXD may seem somewhat expensive. For this reason, I mainly use LXC instead of LXD. The details are described as follows.

Storage (Area for files in a container)

LXC

The files in a container are placed under /var/lib/lxc/[container name]/rootfs on the host OS as they are. From the host's perspective, it is like file sharing by default.

LXD

By default, LXD creates a storage pool file for loop-back mount on the host OS. At the point, the file has to be fixed (E.g. 100GiB).

Becase this stoge pool file is thin-provisioning This storage pool file is thin provisioned, so its initial size is 0. It increase as it's used. However, the file size never reduces when a container or a file in a container is deleted. This is stressful for personal use. Although the storage pool file can be expanded, deciding how much the maximum size should be at the beginning is a difficult task.
Partitioning, such as btrfs on a storage pool loopback file, has some advantages, such as fast snapshot and container copying. However, in my usage, I have little use for taking snapshots while it is running. The containers themselves are not that bloated, so even if I have to copy them, it only takes a short wait. Therefore, I can't take advantage of these benefits nearly as much.

The same thing is also possible with LXC. Just create a user's own loopback mount file, formats it with btrfs, and sets rootfs on top of it.

Configuration

LXC

All configurations are in a file: /var/lib/lxc/[container name]/config. When a user changes a configuration, he/she just edits this one text file. A use can also save the configuration by backing up this file.

LXD

Commands such as `lxc config` can be used. It is a little inconvenient to load and save all configuration at once.

How to install

LXC

It can be installed with the default installer `apt` on Debian and Ubuntu.

LXD

It can be provided by snap. snap is not so major. Using multiple package management system makes a system complicated and is not happy.Roughly speaking, LXD is an enhanced version of LXC with management functions to make it easier to use for large-scale operations. When used by individuals as a simple virtual machine, the functions of LXD may seem somewhat expensive. For this reason, I mainly use LXC instead of LXD. The details are described as follows.

Storage (Area for files in a container)

LXC

The files in a container are placed under /var/lib/lxc/[container name]/rootfs on the host OS as they are. From the host's perspective, it is like file sharing by default.

LXD

By default, LXD creates a storage pool file for loop-back mount on the host OS. At the point, the file has to be fixed (E.g. 100GiB).

Becase this stoge pool file is thin-provisioning This storage pool file is thin provisioned, so its initial size is 0. It increase as it's used. However, the file size never reduces when a container or a file in a container is deleted. This is stressful for personal use. Although the storage pool file can be expanded, deciding how much the maximum size should be at the beginning is a difficult task.
Partitioning, such as btrfs on a storage pool loopback file, has some advantages, such as fast snapshot and container copying. However, in my usage, I have little use for taking snapshots while it is running. The containers themselves are not that bloated, so even if I have to copy them, it only takes a short wait. Therefore, I can't take advantage of these benefits nearly as much.

The same thing is also possible with LXC. Just create a user's own loopback mount file, formats it with btrfs, and sets rootfs on top of it.

Configuration

LXC

All configurations are in a file: /var/lib/lxc/[container name]/config. When a user changes a configuration, he/she just edits this one text file. A use can also save the configuration by backing up this file.

LXD

Commands such as `lxc config` can be used. It is a little inconvenient to load and save all configuration at once.

How to install

LXC

It can be installed with the default installer `apt` on Debian and Ubuntu.

LXD

It can be provided by snap. snap is not so major. Using multiple package management system makes a system complicated and is not happy.

Masquerade by iptables in Linux servers

IP Masquerade

In an environment where security and other details are not a concern, a Linux machine can be simply turned into a router with NAT functionality, as in the following example.
The following example masquerades (forwards packets from 192.168.118.0/24 by making the source IP of the packet look like this machine). This is often useful when communicating with external nodes from a machine inside a private network. The following command is executed on the Router machine shown in the figure.
# iptables -t nat -A POSTROUTING -s 192.168.118.0/24 -j MASQUERADE 


Access from external

When you want to access a machine on 192.168.118.0/24 from the outside, use DNAT. The following is an example of forwarding packets to port 8022 of the Router machine being used as a router to port 22 of 192.168.118.10.
# iptables -t nat -A PREROUTING -p tcp --dport 8022 -j DNAT --to-destination 192.168.118.10:22


Note

In addition to the above, IP routing must be allowed in the first place. If necessary, the following settings should also be made
# echo 1 > /proc/sys/net/ipv4/ip_forward