Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages

  
 
  

home | help
APPJAIL-TUTORIAL(7)	Miscellaneous Information Manual   APPJAIL-TUTORIAL(7)

NAME
       appjail-tutorial	-- A tutorial introduction to AppJail

DESCRIPTION
       Welcome to the AppJail tutorial!

       AppJail is out of the box in many cases and does	not need configuration
       files  or third-party applications to work properly, however, this does
       not mean	that AppJail is	suitable for all kind of users without config-
       uring it	and does not mean that you cannot  take	 advantage  of	third-
       party projects to provide more features.

       NOTE: Sections are unordered, so	you can	jump to	the section you	really
       need.

       This tutorial is	divided	into the following sections:

       Introduction
	     Introduction  to the most basic commands to download FreeBSD com-
	     ponents, create a jail and	list the jails we have created.

       External	Interface
	     Configuring the external interface, so that jails can access  the
	     outside  and clients can connect to applications inside the jails
	     using features such as NAT	and port forwarding.

       Configuration
	     Configuring some basic parameters explicitly to  improve  perfor-
	     mance and stability.

       Loopback	Interface
	     Configuring  the  loopback	interface if we	want to	use LinuxJails
	     in	combination with Virtual Networks.

       Packet Filter
	     Configuring our packet filter with	pf(4) anchors, so  that	 jails
	     can use NAT and port forwarding thanks to Virtual Networks.

       Virtual Networks
	     Quick  explanation	 of  how  to  create  a	 jail and join it to a
	     Virtual Network.

       DNS   Using meaningful names instead of dotted IPv4 addresses  is  very
	     useful  in	 many cases, so	AppJail	can use	the Domain Name	System
	     <DNS> to take advantage of	this feature.

       RC Scripts
	     AppJail uses some RC scripts to start jails  at  startup,	enable
	     NAT  for  an entire network instead of per	jail, supervise	jails,
	     update DNS	information, etc. All of them are optional and you may
	     or	may not	need them.

       Resource	Limits
	     Uncontrolled applications can exacerbate  our  system  resources,
	     but  having  an application inside	a jail is very useful since we
	     can limit the resources to	what it	really needs.

       ZFS   The most advanced file system available  today  for  FreeBSD  and
	     valid for AppJail is what we want to use when possible.

INTRO
       To  create a very basic jail, only two things are needed: obtaining the
       FreeBSD components <base.txz, lib32.txz,	...> and creating the jail us-
       ing those components.

	     # appjail fetch
	     # appjail update release
	     # appjail quick jbasic start

       appjail-fetch(1)	will download MANIFEST and the	components  listed  in
       COMPONENTS  specified  in  your AppJail configuration file. By default,
       only (base.txz) is downloaded.  MANIFEST	contains the component	check-
       sums, so	appjail-fetch(1) can check if they are incorrect.

       After   retrieving   the	  components,	update	 your	release	 using
       appjail-update(1).  At this point you can create	jails using those com-
       ponents with appjail-quick(1).  In the previous case only the start op-
       tion is specified, so our jail will start after its creation.

       That's all! You have a jail! A very simple and basic jail with no  cus-
       tomization, no colors and no powers. Be patient,	you'll wonder how many
       things  you  can	do with	AppJail, from basic <create jails, start them,
       destroy them, ...> to more advanced <deploy complex applications	 using
       Makejails,  each	of them	in separate jails with an active supervisor to
       avoid time of inactivity, ...>

       List the	jails you have created using  appjail-jail(1)  with  the  list
       subcommand.

	     # appjail jail list
	     STATUS  NAME    TYPE  VERSION	 PORTS	NETWORK_IP4
	     UP	     jbasic  thin  14.0-RELEASE	 -	-

       Log in to your jail.

	     # appjail login jbasic

       Stop your jail.

	     # appjail stop jbasic

       And destroy it.

	     # appjail jail destroy jbasic

EXTERNAL INTERFACE
       To  avoid  wasting  precious  time getting the external interface every
       time AppJail <and its child processes!> runs, it's a good idea  to  ex-
       plicitly	 configure an external interface in your AppJail configuration
       file. More than performance it's	about stability, which is  more	 rele-
       vant  when  you	have more than one interface you want to use with your
       jails, so AppJail will only use the one you explicitly configure.

       Another recommendation is to change the name of	your  external	inter-
       face.  This  is not necessary for AppJail, but it is necessary for you,
       as it is	much easier to change one interface for	another	 without  your
       jails  noticing	under normal circumstances. Another reason is when you
       can use the same	interface name on almost, if not all, of your servers,
       so you have fewer things	to consider.  AppJail  is  designed  with  the
       aforementioned  problem	in  mind,  so  it is dynamic in	almost all its
       phases, however,	we recommend changing the interface name  when	possi-
       ble.

	     # sysrc ifconfig_<interface>_name="<custom	name>"
	     # sysrc ifconfig_<custom name>="<options>"

       For  example:  Suppose we want to use em0 as our	external interface and
       we want to change its name to jext and configure	it using DHCP.

	     # sysrc ifconfig_em0_name="jext"
	     # sysrc ifconfig_jext="DHCP"

       You can apply the same steps on another system but with a different in-
       terface,	say, if_re(4).

       For the above changes to	take effect, we	must restart etc/rc.d/netif.

	     # service netif restart

       We recommend performing the above steps physically, so that any	errors
       can  be	fixed  as  soon	 as possible. Or at least you should have some
       other way to fix	any networking related errors.

       The last	step is	to put the EXT_IF parameter in your AppJail configura-
       tion file, which	is commonly /usr/local/etc/appjail/appjail.conf:

	     EXT_IF=jext

CONFIGURATION
       As mentioned, AppJail doesn't require  a	 configuration	file  to  work
       properly,  but  it's  a good idea to have one to	get better performance
       and stability, so we only use what we explicitly	configure. Not all pa-
       rameters	 are  listed  here,  these  are	  just	 a   complement,   see
       appjail-conf(5)

       EXT_IF
	     External Interface. In almost all cases, the interface you	use to
	     access the	network.

	     See "EXTERNAL INTERFACE".

       ON_IF
	     The  name	or  group of the network interface to transmit packets
	     on. In almost all cases, it must have the same value as EXT_IF.

	     See "EXTERNAL INTERFACE".

       FREEBSD_VERSION
	     Default FreeBSD version without patch level that jails will use.

       FREEBSD_ARCH
	     Default FreeBSD architecture that jails will use.

       IMAGE_ARCH
	     Default architecture used by AppJail images.

       SHORTEN_DOMAIN_NAMES
	     It	is used	to shorten the domain name of your jails, so that  you
	     can  communicate  between them using only their name, i.e.	 redis
	     instead of	redis.ajnet.appjail when using the DNS system.

       ENABLE_ZFS
	     If	you plan to take advantage of ZFS with AppJail,	set  this  op-
	     tion.

       Configuration example:

	     EXT_IF=jext
	     ON_IF=jext
	     FREEBSD_VERSION=14.0-RELEASE
	     FREEBSD_ARCH=amd64
	     IMAGE_ARCH=amd64
	     SHORTEN_DOMAIN_NAMES=1
	     # Remove the # character if you want to use ZFS with AppJail.
	     #ENABLE_ZFS=1

LOOPBACK INTERFACE
       Since LinuxJails	uses aliasing in combination with Virtual Networks, we
       need to clone a loopback	interface.

	     # sysrc cloned_interfaces+="lo1"
	     # sysrc ifconfig_lo1_name="appjail0"

PACKET FILTER
       An  application inside a	jail is	not as useful when they	need to	commu-
       nicate with external clients. To	enable this, we	need to	enable	pf(4),
       pflog(4)	and add	some anchors to	our pf.conf(5).

	     # sysrc pf_enable="YES"
	     # sysrc pflog_enable="YES"

       /etc/pf.conf:

	     nat-anchor	"appjail-nat/jail/*"
	     nat-anchor	"appjail-nat/network/*"
	     rdr-anchor	"appjail-rdr/*"

       Restart the rc scripts:

	     service pf	restart
	     service pflog restart

       Some AppJail features require you to enable IPv4	forwarding.

	     # sysrc gateway_enable="YES"
	     # sysctl net.inet.ip.forwarding=1

VIRTUAL	NETWORKS
       In  early  versions  of AppJail,	when you want to create	a jail that is
       part of a Virtual Network, you must first explicitly create the virtual
       network.	You can	do this	if you want, but we recommend that  you	 leave
       that  responsibility  to	 AppJail. AppJail has the ability to automati-
       cally create a virtual network with some	default	values when you	create
       a jail.

	     # appjail quick jtest \
		     start \
		     overwrite=force \
		     virtualnet=":<random> default" \
		     nat

       If you want more	details	 see  appjail-nat(1),  appjail-network(1)  and
       appjail-quick(1),  but  basically  we  have  created a jail named jtest
       which will have an interface with a randomly chosen name	thanks to  the
       <random>	 keyword.  The left part of the	character : is to indicate the
       virtual network that we want to use. If we leave	that part empty	<as we
       do> will	use the	default	virtual	network. The default  virtual  network
       is created if it	does not exist.

DNS
       AppJail	does not come with a DNS server	nor does it officially support
       one, but	it does	come with a configuration for dns/dnsmasq  and	gener-
       ates  a file similar to hosts(5)	that can be consumed by	DNSMasq	or any
       other. In theory, you can use any other DNS server; see	appjail-dns(8)
       for more	details.

	     # appjail-dns
	     10.0.0.1	     ajnet.appjail
	     10.0.0.2	     jtest jtest.ajnet.appjail

       As  mentioned,  this script generates a file similar to hosts(5), so we
       only need to tell a DNS system how to consume it. In the	case  of  DNS-
       Masq, we	just need to enable, configure and start some RC scripts.

	     # sysrc appjail_dns_enable="YES"
	     # sysrc dnsmasq_enable="YES"
	     # sysrc dnsmasq_conf="/usr/local/share/appjail/files/dnsmasq.conf"
	     # touch /var/tmp/appjail-hosts
	     # service dnsmasq start
	     # service appjail-dns start

       That's all, but we have a new problem: what IP address should our jails
       use to send DNS queries?	That depends entirely on your environment, but
       in  many	 cases,	 or at least for AppJail, you only need	a private IPv4
       address,	so we'll configure a tap(4) interface and set  a  single  IPv4
       address.	 We recommend using this IP address instead of the host	IP ad-
       dress because it	is much	easier to migrate  between  environments  this
       way:  if	 you  use  the host IP address and move	to another environment
       with different network parameters, you must change  resolv.conf(5)  for
       each  jail, which is not	really hard even when you have many jails, but
       it is preferable	to change things as little as possible.

	     # sysrc cloned_interfaces+="tap0"
	     # sysrc ifconfig_tap0_name="ajdns"
	     # sysrc ifconfig_ajdns="inet 172.0.0.1/32"
	     # service netif cloneup
	     # service netif start ajdns

       The next	step is	to decide how our jails	 copy  resolv.conf(5).	 There
       are  many  ways,	 but  we  recommend the	most trivial and simplest: set
       DEFAULT_RESOLV_CONF in appjail.conf(5) to  a  resolv.conf(5)  file,  so
       that  AppJail copies it instead of /etc/resolv.conf.  Why is it prefer-
       able  to	 use  an  explicitly  resolv.conf(5)   pathname	  instead   of
       /etc/resolv.conf?   Some	 applications  can modify /etc/resolv.conf, so
       our jails will break their connections due to DNS issues.

	     DEFAULT_RESOLV_CONF="/usr/local/etc/appjail/resolv.conf"

       Our resolv.conf(5) file at /usr/local/etc/appjail/ should be very  sim-
       ple.

	     nameserver	172.0.0.1

       Now  our	jails can use a	DNS hostname to	communicate with another jail.
       That is fine, but we might want to do the same task  on	the  host,  so
       we'll  need  to	configure  /etc/resolv.conf to point to	the address we
       configured for the ajdns	interface. Very	trivial, the  problem  is  the
       one  we	mentioned: some	applications can modify	that file, but a solu-
       tion may	be to set the schg flag, preventing the	modification  of  that
       file.  Consider whether this will break your existing applications, but
       in many cases it	will not.

       After successful	configuration, you can resolve DNS hostnames  to  IPv4
       addresses.

	     # appjail jail list -j jtest
	     STATUS  NAME   TYPE  VERSION	PORTS  NETWORK_IP4
	     UP	     jtest  thin  14.0-RELEASE	-      10.0.0.2
	     # host jtest.ajnet.appjail
	     jtest.ajnet.appjail has address 10.0.0.2

       If  you	set SHORTEN_DOMAIN_NAMES=1 in your AppJail configuration file,
       you can use only	the jail name.

	     # host jtest
	     jtest has address 10.0.0.2

RC SCRIPTS
       Some RC scripts are part	of AppJail and are commonly used to perform  a
       task in the background or only during startup.

       etc/rc.d/appjail
	  This	RC  script has the responsibility of starting jails at startup
	  in the background and	stopping them in the  foreground.  The	reason
	  for  starting	 jails	in  the	 background  is	that the user probably
	  doesn't want to wait for each	of  its	 jails	to  say	 (I'm  up  and
	  running!) The	stop part must be in the foreground for	rc.shutdown(8)
	  to work correctly.

       etc/rc.d/appjail-dns
	  This RC script is responsible	for updating the DNS information, that
	  is, updating the hostname with the IPv4 address of the jail.

	  See "DNS".

       etc/rc.d/appjail-health
	  This	RC  script will	start any healthcheckers you configure for any
	  of your jails	in the background. Note	that the purpose  of  this  RC
	  script  and  healthcheckers  is not to run forever: it will run only
	  until	no more	healthcheckers are running.  You must restart this  RC
	  script every time you	add a new healthchecker	or change a parameter.
	  This	 means	that  if  you  exhaust	your  recovery	attempts,  the
	  healthchecker	will stop and won't run	until you  run	it  again.  We
	  recommend that you don't run healthcheckers forever, fix your	appli-
	  cation!

       etc/rc.d/appjail-natnet
	  You  can perform NAT per jail	or per network.	Typically, NAT is per-
	  formed per jail, but there are some advantages to performing NAT per
	  network as you only need to do it once and not more. Of  course,  it
	  may not be wise to perform NAT for an	entire network.	This RC	script
	  is responsible for performing	NAT per	network	at startup.

RESOURCE LIMITS
       For  resource limits to work in AppJail and in general, you must	enable
       RACCT in	your loader.conf(5) file and reboot your system.

	     kern.racct.enable=1

ZFS
       To take advantage of this amazing, powerful and	advanced  file	system
       with  AppJail,  you  must  enable it using ENABLE_ZFS=1 in your AppJail
       configuration file. There are other  parameters	you  should  consider,
       such  as	 ZPOOL,	 the  pool you want to use, which by default is	zroot;
       ZROOTFS,	the datasets root part,	 which	by  default  is	 appjail;  and
       ZOPTS,  parameters  passed  to  zfs-create(8),  which  by default is -o
       compress=lz4.  You need to escape the shell characters for the last pa-
       rameter.

SEE ALSO
       appjail(1)  appjail-fetch(1)   appjail-healthcheck(1)   appjail-help(1)
       appjail-jail(1)	 appjail-limits(1)   appjail-nat(1)   appjail-quick(1)
       appjail-usage(1)	appjail-conf(5)	pf.conf(5) rc.conf(5) appjail-dns(8)

AUTHORS
       Jess Daniel Colmenares Oviedo <DtxdF@disroot.org>

BUGS
       Don't mix ZFS and non-ZFS file systems!
	   AppJail assumes that	the user has correctly configured  before  use
	   whether  it	want  to  use ZFS or not, i.e. it sets ENABLE_ZFS=1 or
	   ENABLE_ZFS=0.  If you already have  an  AppJail  installation  with
	   data, you must remove or migrate it.

	   In any case if you have started jails, you must stop	them all.

		 service appjail stop

	   <ZFS: Removing> Assuming ZPOOL is zroot and ZROOTFS is appjail:

		 zfs destroy -Rf zroot/appjail

	   <non-ZFS: Removing> Assuming	PREFIX is /usr/local:

		 chflags -R 0 /usr/local/appjail
		 rm -rf	/usr/local/appjail
		 rm -f /var/log/appjail.log
		 rm -rf	/var/log/appjail

	   <Migrating> Change the LOGDIR and PREFIX parameters in your AppJail
	   configuration  file	to  a  different  path	or create a backup and
	   delete those	directories.

	   <ZFS	or non-ZFS> After cleaning you must decide whether you want to
	   use ZFS or not. Review any ZFS-related AppJail configuration	 para-
	   meters  before enabling it. After you set ENABLE_ZFS=1 and run App-
	   Jail, the datasets are automatically	created	in the pool you	speci-
	   fied.

NOTES
       AppJail Documentation: https://appjail.readthedocs.io/

FreeBSD	Ports 14.quarterly	March 12, 2024		   APPJAIL-TUTORIAL(7)

Want to link to this manual page? Use this URL:
<https://man.freebsd.org/cgi/man.cgi?query=appjail-tutorial&sektion=7&manpath=FreeBSD+Ports+14.3.quarterly>

home | help