How the gitlab-ci cache is working on docker runner? what is /cache directory? what is cache_dir? - gitlab-ci

How the gitlab-ci cache is working on docker runner?
What is /cache directory?
What is cache_dir?
Where and how files matching the "paths" in "cache" gitlab-ci.yml are stored?

Volume mounted to /cache directory is created automatically on gitlab-runner installation and managed by cache_dir setting
more about cache_dir:
https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runners-section
https://gitlab.com/gitlab-org/gitlab-runner/blob/main/docs/executors/docker.md#the-builds-and-cache-storage
If you modify the /cache storage path, you also need to make sure to mark this
directory as persistent by defining it in volumes = ["/my/cache/"] under the
[runners.docker] section in config.toml.
TLDR
/cache dir is different from cache config in gitlab-ci.yml
/cache dir in job container is where the cached files are stored
files matching to cache config in gitlab-ci.yml are copied to /cache/$CI_PROJECT_NAMESPACE/$CI_PROJECT_NAME/<cache-key>-<cache-number> at the end of job
The "Clear Runner Caches" button in your project "Pipelines" page schedules TO NOT extract /cache/$CI_PROJECT_NAMESPACE/$CI_PROJECT_NAME/<cache-key>-<cache-number>/cache.zip to dir specified in cache config in gitlab-ci.yml (Instead of "removing content of /cache folder as I though at first)
P.S.
There is container named gitlab-runner-cache created on machine with gitlab-runner (https://gitlab.com/gitlab-org/gitlab-runner/blob/af343971874198a1923352107409583b78e8aa80/executors/docker/executor_docker.go#L382)
(Seems like) This container is used to create anonymous volume where /cache data is stored. After the anonymous volume is created this container is stopped.
The job containers (meaning container were your tests typically run) mounts this anonymous volume
Proofs
HAVING gitlab-ci.yml
image: srghma/docker-nixos-with-git-crypt
cache:
key: "test00000" # to reset cache - change this key OR clear cache in project settings page
paths:
- .mycache # gitlab allows only cache dirs that are relative to project root OR /cache (created automatically)
testtest:
script:
- nix-env -i tree
- tree --dirsfirst -L 4 /cache
- ls -al ./.mycache || true
- echo "test" > /cache/test
- mkdir -p ./.mycache
- echo "test" > ./.mycache/test
- tree --dirsfirst -L 4 /cache
- ls -al ./.mycache || true
Output:
on first run
Running with gitlab-runner 11.6.0 (f100a208)
on srghma_gitlab_runner 9b3980da
Using Docker executor with image srghma/docker-nixos-with-git-crypt ...
Pulling docker image srghma/docker-nixos-with-git-crypt ...
Using docker image sha256:ad3491aae178f629df713e0719750cc445b4881702b6b04b7cf325121f0032bf for srghma/docker-nixos-with-git-crypt ...
Running on runner-9b3980da-project-222-concurrent-0 via myrunner.com...
Fetching changes...
Removing .mycache/
HEAD is now at 675caa7 feat: cache update
From https://gitlab.com/srghma/myproject
675caa7..3d1e223 nix -> origin/nix
Checking out 3d1e2237 as nix...
Skipping Git submodules setup
Checking cache for test00000-11...
No URL provided, cache will be not downloaded from shared cache server. Instead a local version of cache will be extracted.
Successfully extracted cache
$ nix-env -i tree
installing 'tree-1.8.0'
these paths will be fetched (0.03 MiB download, 0.09 MiB unpacked):
/nix/store/dhfq0dsg9a0j5ai78bmh5qlrla8wvcxz-tree-1.8.0
copying path '/nix/store/dhfq0dsg9a0j5ai78bmh5qlrla8wvcxz-tree-1.8.0' from 'https://cache.nixos.org'...
building '/nix/store/dankqr2x4g5igc4w7lw9xqnn7lcy4f7a-user-environment.drv'...
created 233 symlinks in user environment
$ tree --dirsfirst -L 4 /cache
/cache
0 directories, 0 files
$ ls -al ./.mycache || true
$ echo "test" > /cache/test
ls: ./.mycache: No such file or directory
$ mkdir -p ./.mycache
$ echo "test" > ./.mycache/test
$ tree --dirsfirst -L 4 /cache
/cache
`-- test
0 directories, 1 file
$ ls -al ./.mycache || true
total 12
drwxr-xr-x 2 root root 4096 Feb 24 11:44 .
drwxrwxrwx 20 root root 4096 Feb 24 11:44 ..
-rw-r--r-- 1 root root 5 Feb 24 11:44 test
Creating cache test00000-11...
.mycache: found 2 matching files
No URL provided, cache will be not uploaded to shared cache server. Cache will be stored only locally.
Created cache
Job succeeded
on second run
Running with gitlab-runner 11.6.0 (f100a208)
on srghma_gitlab_runner 9b3980da
Using Docker executor with image srghma/docker-nixos-with-git-crypt ...
Pulling docker image srghma/docker-nixos-with-git-crypt ...
Using docker image sha256:ad3491aae178f629df713e0719750cc445b4881702b6b04b7cf325121f0032bf for srghma/docker-nixos-with-git-crypt ...
Running on runner-9b3980da-project-222-concurrent-0 via myrunner.com...
Fetching changes...
Removing .mycache/
HEAD is now at 3d1e223 feat: cache update
Checking out 3d1e2237 as nix...
Skipping Git submodules setup
Checking cache for test00000-11...
No URL provided, cache will be not downloaded from shared cache server. Instead a local version of cache will be extracted.
Successfully extracted cache
$ nix-env -i tree
installing 'tree-1.8.0'
these paths will be fetched (0.03 MiB download, 0.09 MiB unpacked):
/nix/store/dhfq0dsg9a0j5ai78bmh5qlrla8wvcxz-tree-1.8.0
copying path '/nix/store/dhfq0dsg9a0j5ai78bmh5qlrla8wvcxz-tree-1.8.0' from 'https://cache.nixos.org'...
building '/nix/store/dankqr2x4g5igc4w7lw9xqnn7lcy4f7a-user-environment.drv'...
created 233 symlinks in user environment
$ tree --dirsfirst -L 4 /cache
/cache
|-- srghma
| `-- myproject
| `-- test00000-11
| `-- cache.zip
`-- test
3 directories, 2 files
$ ls -al ./.mycache || true
total 12
drwxr-xr-x 2 root root 4096 Feb 24 11:44 .
drwxrwxrwx 20 root root 4096 Feb 24 11:44 ..
-rw-r--r-- 1 root root 5 Feb 24 11:44 test
$ echo "test" > /cache/test
$ mkdir -p ./.mycache
$ echo "test" > ./.mycache/test
$ tree --dirsfirst -L 4 /cache
/cache
|-- srghma
| `-- myproject
| `-- test00000-11
| `-- cache.zip
`-- test
3 directories, 2 files
$ ls -al ./.mycache || true
total 12
drwxr-xr-x 2 root root 4096 Feb 24 11:44 .
drwxrwxrwx 20 root root 4096 Feb 24 11:44 ..
-rw-r--r-- 1 root root 5 Feb 24 11:44 test
Creating cache test00000-11...
.mycache: found 2 matching files
No URL provided, cache will be not uploaded to shared cache server. Cache will be stored only locally.
Created cache
Job succeeded
after you clear cache by clicking on "Clear Runner Caches" in your project "Pipelines" page
Running with gitlab-runner 11.6.0 (f100a208)
on srghma_gitlab_runner 9b3980da
Using Docker executor with image srghma/docker-nixos-with-git-crypt ...
Pulling docker image srghma/docker-nixos-with-git-crypt ...
Using docker image sha256:ad3491aae178f629df713e0719750cc445b4881702b6b04b7cf325121f0032bf for srghma/docker-nixos-with-git-crypt ...
Running on runner-9b3980da-project-222-concurrent-0 via myrunner.com...
Fetching changes...
Removing .mycache/
HEAD is now at 3d1e223 feat: cache update
Checking out 3d1e2237 as nix...
Skipping Git submodules setup
Checking cache for test00000-12...
No URL provided, cache will be not downloaded from shared cache server. Instead a local version of cache will be extracted.
Successfully extracted cache
$ nix-env -i tree
installing 'tree-1.8.0'
these paths will be fetched (0.03 MiB download, 0.09 MiB unpacked):
/nix/store/dhfq0dsg9a0j5ai78bmh5qlrla8wvcxz-tree-1.8.0
copying path '/nix/store/dhfq0dsg9a0j5ai78bmh5qlrla8wvcxz-tree-1.8.0' from 'https://cache.nixos.org'...
building '/nix/store/dankqr2x4g5igc4w7lw9xqnn7lcy4f7a-user-environment.drv'...
created 233 symlinks in user environment
$ tree --dirsfirst -L 4 /cache
/cache
|-- srghma
| `-- myproject
| `-- test00000-11
| `-- cache.zip
`-- test
3 directories, 2 files
$ ls -al ./.mycache || true
ls: ./.mycache: No such file or directory
$ echo "test" > /cache/test
$ mkdir -p ./.mycache
$ echo "test" > ./.mycache/test
$ tree --dirsfirst -L 4 /cache
/cache
|-- srghma
| `-- myproject
| `-- test00000-11
| `-- cache.zip
`-- test
3 directories, 2 files
$ ls -al ./.mycache || true
total 12
drwxr-xr-x 2 root root 4096 Feb 24 11:45 .
drwxrwxrwx 20 root root 4096 Feb 24 11:45 ..
-rw-r--r-- 1 root root 5 Feb 24 11:45 test
Creating cache test00000-12...
.mycache: found 2 matching files
No URL provided, cache will be not uploaded to shared cache server. Cache will be stored only locally.
Created cache
Job succeeded

Related

Mount host directory to docker/podman container with correct permissions

Using:
podman version 4.2.0
AlmaLinux 8.7
I've created an image based on redhat/ubi8 with the following Dockerfile:
FROM docker.io/redhat/ubi8
RUN dnf install -y gcc-c++ cmake python39 openssh git
RUN useradd -ms /bin/bash foobar -g users
USER foobar
WORKDIR /home/foobar/
RUN mkdir -p .ssh
$ docker build -t mount_test_image .
I run the image from a directory that contains a directory ssh, and I want to mount that directory to /home/foobar/.ssh with ownership of foobar.users
$ ls -l
-rw-r--r--. 1 host_user users 269 Dec 7 09:10 Dockerfile
drwxrwxr-x. 2 host_user users 18 Dec 2 10:41 ssh
docker run -it -d --rm --mount type=bind,src=ssh,target=/home/foobar/.ssh --name=mount_test mount_test_image
However when I enter the container via
docker exec -it mount_test '/bin/sh'
The home directory looks like this:
drwx------. 1 foobar users 18 Dec 7 17:10 .
drwxr-xr-x. 1 root root 21 Dec 7 17:10 ..
-rw-r--r--. 1 foobar users 18 Jun 20 11:31 .bash_logout
-rw-r--r--. 1 foobar users 141 Jun 20 11:31 .bash_profile
-rw-r--r--. 1 foobar users 376 Jun 20 11:31 .bashrc
drwxrwxr-x. 2 root root 18 Dec 2 18:41 .ssh
I obviously get a "permission denied" when trying to access that directory.
sh-4.4$ ls /home/foobar/.ssh
ls: cannot open directory '/home/foobar/.ssh': Permission denied
I tried changing the ownership of the directory on the host to match the uid of the container user, but then it just looks like this:
drwxrwxr-x. 2 nobody root 18 Dec 2 18:41 .ssh
My host user uid:gid is 501:100 and the container user is 1000:100. Right now I'm just trying to generate an ssh key to upload to bitbucket, but this seems like a simple feature a container should be have. All the tutorials and examples just stop after the --mount command instruction and say "there ya go!". What good is the mount point if you can't read/write it?
EDIT:
I tried on Archlinux using docker instead of podman and it works like one would expect with both -v and --mount. The owner of the mounted directory in the container matches the uid and gid of the host. Is this then a bug in podman or is it just done differently?
You are using a non-root user (foobar) in a rootless container. You must use --userns=keep-id for the container user to see the mounted volumes.
https://github.com/containers/podman/blob/main/docs/tutorials/rootless_tutorial.md#using-volumes

gitlab ci cache no matching files

I try to build apk with gitlab runner
When I build apk, I don't want download all build pacakage everytime
so i try to caching .gradle/caches and .gradle/wrappers
following is my gitlab-ci.yml
sdk_build_job
image: myimage:latest
stage: sdk-build
script:
...
cache:
key: gradle-cache
- /root/.gradle/caches
- /root/.gradle/wrapper
but create gradle-cache always make an warning
Creating cache gradle-cache...
WARNING: /root/.gradle/caches: no matching files
WARNING: /root/.gradle/wrapper: no matching files
Archive is up to date!
I don't know why can't find caches and wrapper directory
When i into docker container and find the folders, there were well positioned
root#runner-3d9fa57b-project-4-concurrent-0:~/.gradle# pwd
/root/.gradle
root#runner-3d9fa57b-project-4-concurrent-0:~/.gradle# ls -al
total 28
drwxr-xr-x 7 root root 4096 Dec 28 02:21 .
drwx------ 1 root root 4096 Dec 28 02:19 ..
drwxr-xr-x 6 root root 4096 Dec 28 02:20 caches
drwxr-xr-x 3 root root 4096 Dec 28 02:19 daemon
drwxr-xr-x 4 root root 4096 Dec 28 02:19 native
drwxr-xr-x 2 root root 4096 Dec 28 02:21 workers
drwxr-xr-x 3 root root 4096 Dec 28 02:19 wrapper
Please help me.......
That is because cache only works for files and folders INSIDE your project. This is poorly documented on the GitLab website IMHO.
So:
cache:
key: gradle-cache
paths:
- /root/.gradle/caches
- /root/.gradle/wrapper
Still only searches in:
/home/user/yourproject/root/.gradle/caches
/home/user/yourproject/root/.gradle/wrapper
For R, I set R_LIBS_SITE to a local folder inside my project. This allowed me to reuse installed packages. Have a look here.
I banged my head on the same issue.
MS Berends is partially right. Caching is supposed to work for files and folders only already within your project directory, see here: https://gitlab.com/gitlab-org/gitlab-ce/issues/4431
There were supposed to be an option of mounting the cache folder as a volume like
[[runners]]
name = ""
url = ""
token = ""
executor = "docker"
[runners.docker]
tls_verify = false
image = "alpine:latest"
privileged = true
disable_entrypoint_overwrite = false
oom_kill_disable = false
disable_cache = false
volumes = ["/cache", "/root/.gradle:/root/.gradle"]
shm_size = 0
But that does not work neither.
What I ended up doing is the following:
In my .gitlab-ci.yaml, I set the GRADLE_USER_HOME to point on the already mapped cache volume like
GRADLE_USER_HOME: "/cache/.gradle"
Then I passed that gradle home variable to the ./gradlew like
./gradlew $GRADLE_ARGS_CI -g $GRADLE_USER_HOME testDebugUnitTest
Notice the argument named $GRADLE_ARGS_CI. It is set to the following value
GRADLE_ARGS_CI: "--no-build-cache --no-daemon --stacktrace"
The --no-build-cache is necessary if you don't want to reuse the build outputs from previous builds. The --no-daemon is a no brainer because the docker build environment is spawned for every build.
I was able to save 2.5 min on my build time with these changes.
cache:
paths:
- .nuget
before_script:
- dotnet --version
- "[ -f .nuget/NuGet/NuGet.Config ] && rm -rf $HOME/.nuget || rsync -a $HOME/.nuget ./"
- ln -s $(pwd)/.nuget $HOME/.nuget

gitlab backup: make gitlab-rake produce tar.gz files not tar

Backup files I get with gitlab-rake are tar files how can I get tar.gz ?
Here the files::
root#gitlab:~# ll /mnt/backup-git/ -h
total 1.9G
-rw------- 1 git git 57M Nov 29 15:57 1480431448_gitlab_backup.tar
-rw------- 1 git git 57M Nov 29 15:57 1480431473_gitlab_backup.tar
-rw------- 1 git git 452M Nov 30 02:00 1480467623_gitlab_backup.tar
Here my configuration values for the backup::
$ grep -i backup /etc/gitlab/gitlab.rb | grep -v '^#'
gitlab_rails['backup_path'] = "/mnt/backup-git/"
gitlab_rails['backup_keep_time'] = 604800
To create them, following the documentation here, (omnibus installation):
root#gitlab:~# crontab -l | grep -v '^#'
0 2 * * * /opt/gitlab/bin/gitlab-rake gitlab:backup:create CRON=1
It doesn't really make sense to compress the gitlab backup tar files. The gitlab backup tar files are the final tarball made during the backup process and the contents are all files compressed during the backup process. You can read more here

httpd in docker cannot start

I'm trying to install HTTPD in docker, I wrote a dockerfile like this:
FROM centos
VOLUME /var/log/httpd
VOLUME /etc/httpd
VOLUME /var/www/html
# Update Yum Repostory
RUN yum clean all && \
yum makecache fast && \
yum -y update && \
yum -y install httpd
RUN yum clean all
EXPOSE 80
CMD /usr/sbin/httpd -D BACKGROUND && tail -f /var/log/httpd/access_log
it works if I run the image without host volumes, but failed if I use parameter:
--volume /data/httpd/var/www/html:/var/www/html --volume /data/httpd/var/log:/var/log --volume /data/httpd/etc:/etc/httpd
the error message is:
httpd: Could not open configuration file /etc/httpd/conf/httpd.conf: No such file or directory
I checked the mount point which is empty:
# ll /data/httpd/etc/
total 0
But if I don't use "volume" by default docker copys over files to a temp folder:
# ll /var/lib/docker/volumes/04f083887e503c6138a65b300a1b40602d227bb2bbb58c69b700f6ac753d1c34/_data
total 4
drwxr-xr-x. 2 root root 35 Nov 3 03:16 conf
drwxr-xr-x. 2 root root 78 Nov 3 03:16 conf.d
drwxr-xr-x. 2 root root 4096 Nov 3 03:16 conf.modules.d
lrwxrwxrwx. 1 root root 19 Nov 3 03:16 logs -> ../../var/log/httpd
lrwxrwxrwx. 1 root root 29 Nov 3 03:16 modules -> ../../usr/lib64/httpd/modules
lrwxrwxrwx. 1 root root 10 Nov 3 03:16 run -> /run/httpd
So I'm confused, why docker refused to copy them to the named location? and how to fix this problem?
This is a documented behavior indeed:
Volumes are initialized when a container is created. If the container’s
base image contains data at the specified mount point, that existing data
is copied into the new volume upon volume initialization. (Note that this
does not apply when mounting a host directory.)
i.e. when you mount the /etc/httpd volume --volume /data/httpd/etc:/etc/httpd, no data will be copied.
You can also see https://github.com/docker/docker/pull/9092 for a more detailed discussion on why it works this way (in case you are interested).
A usual workaround for this is to copy your initial data, to the volume folder (from within the container), inside your ENTRYPOINT or CMD script,
in case it is empty.
Note that your initial dataset must be kept outside the volume folder (e.g. as .tar file in /opt), for this to work, as the volume folder will be shadowed by the host folder mounted over it.
Given below is a sample Dockerfile and Script, which demonstrate the behavior:
Sample Dockerfile
FROM debian:stable
RUN mkdir -p /opt/test/; touch /opt/test/initial-data-file
VOLUME /opt/test
Sample script (try various volume mappings)
#Build image
>docker build -t volumetest .
Sending build context to Docker daemon 2.56 kB
Step 0 : FROM debian:stable
---> f7504c16316c
Step 1 : RUN mkdir -p /opt/test/; touch /opt/test/initial-data-file
---> Using cache
---> 1ea0475e1a18
Step 2 : VOLUME /opt/test
---> Using cache
---> d8d32d849b82
Successfully built d8d32d849b82
#Implicit Volume mapping (as defined in Dockerfile)
>docker run --rm=true volumetest ls -l /opt/test
total 0
-rw-r--r-- 1 root root 0 Nov 4 18:26 initial-data-file
#Explicit Volume mapping
> docker run --rm=true --volume /opt/test volumetest ls -l /opt/test/
total 0
-rw-r--r-- 1 root root 0 Nov 4 18:26 initial-data-file
#Explicitly Mounted Volume
>mkdir test
>docker run --rm=true --volume "$(pwd)/test/:/opt/test" volumetest ls -l /opt/test
total 0
And here is a simple entrypoint script, illustrating a possible workaround:
#!/bin/bash
VOLUME=/opt/test
DATA=/opt/data-volume.tar.gz
if [[ -n $(find "$VOLUME" -maxdepth 0 -empty) ]]
then
echo Preseeding VOLUME $VOLUME with data from $DATA...
tar -C "$VOLUME" -xvf "$DATA"
fi
"$#"
add the following to the Dockerfile
COPY data-volume.tar.gz entrypoint /opt/
ENTRYPOINT ["/opt/entrypoint"]
First run:
>docker run --rm=true --volume "$(pwd)/test/:/opt/test" volumetest ls -l /opt/test
Preseeding VOLUME /opt/test with data from /opt/data-volume.tar.gz...
preseeded-data
total 0
-rw-r--r-- 1 1001 users 0 Nov 4 18:43 preseeded-data
Subsequent runs:
>docker run --rm=true --volume "$(pwd)/test/:/opt/test" volumetest ls -l /opt/test
ls -l /opt/test
total 0
-rw-r--r-- 1 1001 users 0 Nov 4 18:43 preseeded-data
Note, that the volume folder will only be populated with data,
if it was completely empty before.

Lighttpd: specific ~user directory 404

I'm trying to get user directories to work with Lighttpd on Arch Linux. But after creating the public_html directory, placing an index.html file in it, setting permissions, configuring Lighttpd to use the user directory module, and restarting lighttpd, it still gives 404 for one specific user (yet another one works).
Here are my configuration files:
$ cat /etc/lighttpd/lighttpd.conf
# This is a minimal example config
# See /usr/share/doc/lighttpd
# and http://redmine.lighttpd.net/projects/lighttpd/wiki/Docs:ConfigurationOptions
server.port = 80
server.username = "http"
server.groupname = "http"
server.document-root = "/srv/http"
server.errorlog = "/var/log/lighttpd/error.log"
dir-listing.activate = "enable"
index-file.names = ( "index.html" )
mimetype.assign = (
".html" => "text/html",
".txt" => "text/plain",
".css" => "text/css",
".js" => "application/x-javascript",
".jpg" => "image/jpeg",
".jpeg" => "image/jpeg",
".gif" => "image/gif",
".png" => "image/png",
"" => "application/octet-stream"
)
include "conf.d/userdir.conf"
include "conf.d/cgi.conf"
$ cat /etc/lighttpd/conf.d/userdir.conf
server.modules += ( "mod_userdir" )
userdir.path = "public_html"
This is what things look like for user aardbei:
$ cat /home/aardbei/public_html/index.html
doot doot
$ ls -ld /home/aardbei/public_html
drwxrwxrwx 2 aardbei aardbei 4096 Mar 27 13:10 /home/aardbei/public_html
$ ls -ld /home/aardbei/public_html/index.html
-rwxrwxrwx 1 aardbei aardbei 37 Mar 27 13:11 /home/aardbei/public_html/index.html
But even after restarting the server with sudo systemctl restart lighttpd I still get 404 at URI /~aardbei/index.html and not what I should get: "doot doot"
However, this is what things look like for the user madeline:
$ cat /home/madeline/public_html/index.html
blah blah blah
$ ls -ld /home/madeline/public_html/
drwxrwxrwx 19 madeline madeline 4096 Mar 27 13:33 /home/madeline/public_html/
$ ls -ld /home/madeline/public_html/index.html
-rw-r--r-- 1 madeline madeline 15 Mar 27 13:33 /home/madeline/public_html/index.html
So the important parts are the same. And yet going to URI /~madeline/index.html does what it should do: it shows "blah blah blah"
Nothing looks relevant here, but here are groups for the two users:
$ groups madeline
wheel video audio wireshark madeline
$ groups aardbei
wheel aardbei
What is going on? Why doesn't the user directory for the user aardbei work in Lighttpd?
Following the instructions on the Arch Linux wiki for Apache worked: https://wiki.archlinux.org/index.php/Apache_HTTP_Server#User_directories
$ chmod o+x /home/aardbei
$ chmod o+x /home/aardbei/public_html
$ chmod -R o+r /home/aardbei/public_html
I'm still not sure I understand the permissions at play here, but it solves my problem.
The reason that the accepted answer works is due to the user that the web server is running as requiring access to the user's home directory in order to access their public_html.
Granting o+x allows other users to access a file and/or sub-directory within but not allow them to list the contents of a directory. Basically they can pass through it so long as they know what they're looking for, public_html, but they cannot get a list of the contents otherwise.
Example
Here's my home directory:
$ ls -dl /home/sam
drwx-----x. 3 sam sam 4096 Nov 3 11:08 /home/sam
$ ls -dl /home/sam/public_html
drwxr-xr-x. 2 sam users 4096 Nov 3 11:09 /home/sam/public_html
Now as the user of the web server, lighttpd, cannot list the contents of my home directory:
$ sudo -u lighttpd ls /home/sam
ls: cannot open directory /home/sam: Permission denied
But can see a specific directory if they happen to know its name:
$ ls -dl /home/sam/public_html
drwxr-xr-x. 2 sam users 4096 Nov 3 11:09 /home/sam/public_html
Here's another directory that the web server can see too:
$ sudo -u lighttpd ls -ld /home/sam/someotherdir
drwx------. 2 sam users 4096 Nov 3 11:22 /home/sam/someotherdir
And files within the public_html are visible as well:
$ ls -dl /home/sam/public_html/index.html
-rw-r--r--. 1 sam users 3 Nov 3 11:09 /home/sam/public_html/index.html
Normal permissions apply here, so if you don't want the web server to see something, make it readonly to your user & groups but not everyone else (others).