add Makefile to guide configuration and perform installation

This change replaces icecast.xml with icecast.xml.template.  A
complete icecast.xml is no-longer provided.

Instead, to create icecast.xml run:

  make

You can generate icecast.xml and then install it:

  make install

This doesn't currently do any aspectss of making the system ready to
run icecast (e.g. performing `sudo apt install icecast2`, or similar).
This commit is contained in:
2025-07-19 18:59:40 -05:00
parent 7b3f1768d2
commit 8f8bb57fd1
3 changed files with 245 additions and 95 deletions

83
Makefile Normal file
View File

@ -0,0 +1,83 @@
# Makefile for shred.ing
# make (default, or with: make config)
# prompt for settings unless .env file exists
# create ~/icecast.xml
# make install
# backup the live config to ~/icecast.xml
# install ~/icecast.xml to /etc/icecast2
# not currently used for anything
## make sure to change these
#source_pass := password_to_share_with_casters
#relay_pass := password_for_icecast2_relays
#admin_user := admin_web_and_api_username
#admin_pass := password_for_admin_access
## probably want to change this
#hostname := shred.ing
# the "prompt" port can be left blank so
# this can be left at default
icecast2_port := 8000
##
## More or less internal stuffs
##
default_config_template := icecast.xml.template
ICECAST_CONFIG_TEMPLATE := $(ICECAST_CONFIG_TEMPLATE)
#ICECAST_CONFIG_TEMPLATE != [ -z "$(ICECAST_CONFIG_TEMPLATE)" ] || echo "$(default_config_template)"
#ICECAST_CONFIG_TEMPLATE := icecast.xml.template.foo
## generate configuration files for icecast2
# these targets aren't associated with files
.PHONEY: config backup-live-config install
## main "entry point" makefile targets
config: icecast.xml .env
backup-live-config:
sudo test -r /etc/icecast2/icecast.xml && sudo cp /etc/icecast2/icecast.xml icecast.xml~~
install: config backup-live-config
sudo cp icecast.xml /etc/icecast2/icecast.xml.new
# this will prompt to build a .env file when none exists
.env:
@echo "You will receive a series of prompts to create a .env file."
@echo
@printf "Enter your icecast hostname (or IP): "
@printf "hostname=%s\n" `read i; echo $$i` >.env
@printf "Enter the port for your icecast server ($(icecast2_port)): "
@printf "icecast2_port=%s\n" "$$( i=`read i; echo $$i`; printf "%s" $$( if test -z "$$i" ; then echo "$(icecast2_port)"; else echo "$$i" ; fi ) )" >>.env
@echo "Icecast requires, potentially, several passwords."
@echo "Passwords entered now are echoed to the screen."
@echo "You can pick bogus values and then edit the .env file."
@printf "Enter a source password: "
@printf "source_pass=%s\n" `read i; echo $$i` >>.env
@printf "Enter a relay password: "
@printf "relay_pass=%s\n" `read i; echo $$i` >>.env
@printf "Enter an admin password: "
@printf "admin_pass=%s\n" `read i; echo $$i` >>.env
@echo "Finally, select a username for the admin account:"
@printf "Enter the icecast admin username: "
@printf "admin_user=%s\n" `read i; echo $$i` >>.env
# this ensures the template icecast config exists
$(ICECAST_CONFIG_TEMPLATE):
@printf "The icecast2 configuration file template "'"'"%s"'"'"\n" "$(ICECAST_CONFIG_TEMPLATE)"
@printf "is missing or cannot be read.\n"
@echo "This can be caused by an incomplete or corrupted checkout or"
@echo "an invalid value for the ICECAST_CONFIG_TEMPLATE env variable."
false
### given we have a template and a .env, create the icecast config
icecast.xml: $(ICECAST_CONFIG_TEMPLATE) .env
perl -e 'BEGIN{open my$$FH,q(<),q(.env) or die $$!; for(<$$FH>){ chomp; my($$k,$$v) = split q(=); next unless $$k; $$k =~ s/^\s+|\s+$$//g; next unless $$k; $$v =~ s/^\s+|\s+//g; $$h{lc $$k} = $$v; }}' -pe 's/\@\@([^@]+)\@\@/$$h{lc $$1}/eig;' >icecast.xml <$(ICECAST_CONFIG_TEMPLATE)
# this seems to work, too!
# cat icecast.xml.template | perl -pe 's/\@\@source_pass\@\@/$(source_pass)/ig; s/\@\@relay_pass\@\@/$(relay_pass)/ig; s/\@\@admin_user\@\@/$(admin_user)/ig; s/\@\@admin_pass\@\@/$(admin_pass)/ig; s/\@\@hostname\@\@/$(hostname)/ig; s/\@\@icecast2_port\@\@/$(icecast2_port)/ig;' > icecast.xml
# probably, so does this?
# cat icecast.xml.template | perl -e 'BEGIN{open my$FH,q(<),q(.env) or die $!; for(<$FH>){ chomp; my($k,$v) = split q(=); next unless $k; $k =~ s/^\s+|\s+$//g; next unless $k; $v =~ s/^\s+|\s+//g; $h{lc $k} = $v; }}' -pe 's/\@\@([^@]+)\@\@/$h{lc $1}/eig;' -e 'END { use Data::Dumper; warn Dumper( \%h ) } ' > foo.xml

View File

@ -7,8 +7,15 @@ Stuff to install on a (nominally) Ubuntu 24 host to create (e.g.) shred.ing to c
- [X] fix issue where streams HTML player disconnects after an hour
- [X] create fallback streams to support switching casters
- [ ] write a tutoral explaining how to use the files in this repo to create a streaming radio station
- [-] build guided installer
- [ ] write a tutoral
# Quick Start
git clone https://code.bru.st/corwin/shred.ing-server.git
apt-get install icecast2
make install
links localhost:8000
# ABSTRACT

View File

@ -1,55 +1,36 @@
<icecast>
<!-- location and admin are two arbitrary strings that are e.g. visible
on the server info page of the icecast web interface
(server_version.xsl). -->
<location>Earth</location>
<admin>icemaster@localhost</admin>
<!-- IMPORTANT!
Especially for inexperienced users:
Start out by ONLY changing all passwords and restarting Icecast.
For detailed setup instructions please refer to the documentation.
It's also available here: http://icecast.org/docs/
-->
<location>The Island of Misfit Toys</location>
<admin>yo@mammy</admin>
<limits>
<clients>100</clients>
<sources>2</sources>
<clients>17q000</clients>
<sources>17</sources>
<queue-size>524288</queue-size>
<client-timeout>30</client-timeout>
<header-timeout>15</header-timeout>
<source-timeout>17</source-timeout>
<!-- If enabled, this will provide a burst of data when a client
first connects, thereby significantly reducing the startup
<!-- If enabled, this will provide a burst of data when a client
first connects, thereby significantly reducing the startup
time for listeners that do substantial buffering. However,
it also significantly increases latency between the source
client and listening client. For low-latency setups, you
might want to disable this. -->
<burst-on-connect>1</burst-on-connect>
<!-- <burst-on-connect>1</burst-on-connect> -->
<!-- same as burst-on-connect, but this allows for being more
specific on how much to burst. Most people won't need to
change from the default 64k. Applies to all mountpoints -->
<burst-size>65535</burst-size>
<!-- <burst-size>65535</burst-size> -->
</limits>
<authentication>
<!-- Sources log in with username 'source' -->
<source-password>$shredsourcepassword$</source-password>
<source-password>@@Source_Pass@@</source-password>
<!-- Relays log in with username 'relay' -->
<relay-password>$shredrelaypassword$</relay-password>
<relay-password>@@Relay_Pass@@</relay-password>
<!-- Admin logs in with the username given below -->
<admin-user>admin</admin-user>
<admin-password>$shredadminpassword$</admin-password>
<admin-user>@@Admin_User@@</admin-user>
<admin-password>@@Admin_Pass@@</admin-password>
</authentication>
<!-- set the mountpoint for a shoutcast source to use, the default if not
specified is /stream but you can change it here if an alternative is
wanted or an extension is required
<shoutcast-mount>/live.nsv</shoutcast-mount>
-->
<!-- Uncomment this if you want directory listings -->
<!--
<directory>
<yp-url-timeout>15</yp-url-timeout>
@ -57,41 +38,14 @@
</directory>
-->
<!-- This is the hostname other people will use to connect to your server.
It affects mainly the urls generated by Icecast for playlists and yp
listings. You MUST configure it properly for YP listings to work!
-->
<hostname>shred.ing</hostname>
<!-- You may have multiple <listen-socket> elements -->
<hostname>@@hostname@@</hostname>
<listen-socket>
<port>8000</port>
<!-- <bind-address>127.0.0.1</bind-address> -->
<!-- <shoutcast-mount>/stream</shoutcast-mount> -->
<port>@@icecast2_port@@</port>
</listen-socket>
<!--
<listen-socket>
<port>8080</port>
</listen-socket>
-->
<!--
<listen-socket>
<port>8443</port>
<ssl>1</ssl>
</listen-socket>
-->
<!-- Global header settings
Headers defined here will be returned for every HTTP request to Icecast.
The ACAO header makes Icecast public content/API by default
This will make streams easier embeddable (some HTML5 functionality needs it).
Also it allows direct access to e.g. /status-json.xsl from other sites.
If you don't want this, comment out the following line or read up on CORS.
-->
<http-headers>
<header name="Access-Control-Allow-Origin" value="*" />
<header name="X-Clacks-Overhead" value="GNU Terry Pratchett" />
</http-headers>
@ -103,12 +57,10 @@
<!--<master-server-port>8001</master-server-port>-->
<!--<master-update-interval>120</master-update-interval>-->
<!--<master-password>hackme</master-password>-->
<!-- setting this makes all relays on-demand unless overridden, this is
useful for master relays which do not have <relay> definitions here.
The default is 0 -->
<!--<relays-on-demand>1</relays-on-demand>-->
<!--
<relay>
<server>127.0.0.1</server>
@ -122,38 +74,152 @@
-->
<!-- Mountpoints
Only define <mount> sections if you want to use advanced options,
like alternative usernames or passwords
-->
<!-- Default settings for all mounts that don't have a specific <mount type="normal">.
<!-- the default mount is the top of the fall-back chain
anyone listening to something pushing to the default
gets seomthing in our fallback chain, isntead.
-->
<mount type="default">
<public>0</public>
<!-- <intro>/server-wide-intro.ogg</intro> -->
<max-listener-duration>3600</max-listener-duration>
<!-- <max-listener-duration>3600</max-listener-duration> -->
<username>live</username>
<password>$shredlivepassword$</password>
<authentication type="url">
<option name="mount_add" value="http://auth.example.org/stream_start.php"/>
</authentication>
<http-headers>
<header name="foo" value="bar" />
</http-headers>
<password>@@Source_Pass@@</password>
<fallback-override>1</fallback-override>
<fallback-mount>/live</fallback-mount>
</mount>
<!-- <mount> -->
<!-- <mount-name>/black.mp3</mount-name> -->
<!-- <fallback-mount>/silver.mp3</fallback-mount> -->
<!-- <fallback-override>1</fallback-override> -->
<!-- </mount> -->
<mount type="normal">
<public>0</public>
<mount-name>/live.ogg</mount-name>
<username>live</username>
<password>@@Source_Pass@@</password>
<fallback-override>1</fallback-override>
<fallback-mount>/gold.ogg</fallback-mount>
</mount>
<mount type="normal">
<public>0</public>
<mount-name>/gold.ogg</mount-name>
<fallback-override>1</fallback-override>
<fallback-mount>/purple.ogg</fallback-mount>
<username>live</username>
<password>@@Source_Pass@@</password>
</mount>
<mount type="normal">
<public>0</public>
<mount-name>/purple.ogg</mount-name>
<fallback-override>1</fallback-override>
<fallback-mount>/black.ogg</fallback-mount>
<username>live</username>
<password>@@Source_Pass@@</password>
</mount>
<mount type="normal">
<public>0</public>
<mount-name>/black.ogg</mount-name>
<fallback-override>1</fallback-override>
<fallback-mount>/silver.ogg</fallback-mount>
<username>live</username>
<password>@@Source_Pass@@</password>
</mount>
<mount type="normal">
<public>0</public>
<!-- <intro>/server-wide-intro.ogg</intro> -->
<!-- <max-listener-duration>3600</max-listener-duration> -->
<mount-name>/silver.ogg</mount-name>
<fallback-override>1</fallback-override>
<fallback-mount>/live.ogg</fallback-mount>
<username>live</username>
<password>@@Source_Pass@@</password>
</mount>
<!-- <mount> -->
<!-- <mount-name>/silver.mp3</mount-name> -->
<!-- <fallback-mount>/black.mp3</fallback-mount> -->
<!-- <fallback-override>1</fallback-override> -->
<!-- </mount> -->
<mount type="normal">
<public>0</public>
<fallback-override>1</fallback-override>
<mount-name>/live</mount-name>
<username>live</username>
<password>@@Source_Pass@@</password>
<fallback-override>1</fallback-override>
<fallback-mount>/live.mp3</fallback-mount>
</mount>
<mount type="normal">
<public>0</public>
<mount-name>/live.mp3</mount-name>
<username>live</username>
<password>@@Source_Pass@@</password>
<fallback-override>1</fallback-override>
<fallback-mount>/gold</fallback-mount>
</mount>
<mount type="normal">
<public>0</public>
<mount-name>/gold</mount-name>
<fallback-override>1</fallback-override>
<fallback-mount>/gold.mp3</fallback-mount>
<username>live</username>
<password>@@Source_Pass@@</password>
</mount>
<mount type="normal">
<public>0</public>
<mount-name>/gold.mp3</mount-name>
<fallback-override>1</fallback-override>
<fallback-mount>/gold.ogg</fallback-mount>
<username>live</username>
<password>@@Source_Pass@@</password>
</mount>
<mount type="normal">
<public>0</public>
<mount-name>/purple</mount-name>
<fallback-override>1</fallback-override>
<fallback-mount>/purple.mp3</fallback-mount>
<username>live</username>
<password>@@Source_Pass@@</password>
</mount>
<mount type="normal">
<public>0</public>
<mount-name>/purple.mp3</mount-name>
<fallback-override>1</fallback-override>
<fallback-mount>/black</fallback-mount>
<username>live</username>
<password>@@Source_Pass@@</password>
</mount>
<mount type="normal">
<public>0</public>
<!-- <intro>/server-wide-intro.ogg</intro> -->
<!-- <max-listener-duration>3600</max-listener-duration> -->
<mount-name>/black</mount-name>
<fallback-override>1</fallback-override>
<fallback-mount>/black.mp3</fallback-mount>
<username>live</username>
<password>@@Source_Pass@@</password>
</mount>
<mount type="normal">
<public>0</public>
<mount-name>/black.mp3</mount-name>
<fallback-override>1</fallback-override>
<fallback-mount>/silver</fallback-mount>
<username>live</username>
<password>@@Source_Pass@@</password>
</mount>
<mount type="normal">
<public>0</public>
<!-- <intro>/server-wide-intro.ogg</intro> -->
<!-- <max-listener-duration>3600</max-listener-duration> -->
<mount-name>/silver</mount-name>
<fallback-override>1</fallback-override>
<fallback-mount>/silver.mp3</fallback-mount>
<username>live</username>
<password>@@Source_Pass@@</password>
</mount>
<mount type="normal">
<public>0</public>
<mount-name>/silver.mp3</mount-name>
<fallback-override>1</fallback-override>
<fallback-mount>/live</fallback-mount>
<username>live</username>
<password>@@Source_Pass@@</password>
</mount>
<!-- Normal mounts -->
<!--
@ -202,16 +268,10 @@
<fileserve>1</fileserve>
<paths>
<!-- basedir is only used if chroot is enabled -->
<basedir>/usr/share/icecast2</basedir>
<!-- Note that if <chroot> is turned on below, these paths must both
be relative to the new root, not the original root -->
<logdir>/var/log/icecast2</logdir>
<webroot>/usr/share/icecast2/web</webroot>
<adminroot>/usr/share/icecast2/admin</adminroot>
<!-- <pidfile>/usr/share/icecast2/icecast.pid</pidfile> -->
<!-- Aliases: treat requests for 'source' path as being for 'dest' path
May be made specific to a port or bound address using the "port"
and "bind-address" attributes.
@ -233,7 +293,7 @@
<logging>
<accesslog>access.log</accesslog>
<errorlog>error.log</errorlog>
<!-- <playlistlog>playlist.log</playlistlog> -->
<playlistlog>playlist.log</playlistlog>
<loglevel>3</loglevel> <!-- 4 Debug, 3 Info, 2 Warn, 1 Error -->
<logsize>10000</logsize> <!-- Max size of a logfile -->
<!-- If logarchive is enabled (1), then when logsize is reached