SERVIZIO WEB ASPNET CORE PUBBLICATO IN AMBIENTE LINUX

(Visual studio code windows, Debian 10 Buster, Virtual Box, Nginx, Proxy inverso Kestrel, MariaDB, HeidiSQL)

1. Visual Studio Code

Installiamo visual studio code e le estensioni C# e C# Extensions

2. Creiamo un progetto vuoto

Apriamo una finestra dos (prompt dei comandi) o PowerShell, spostarsi nella directory in cui si vuole creare il progetto e inizializzarne uno vuoti con il comando:

dotnet new web -n WebApi01

per la lista completa dei template disponibili digitare dotnet new -–help

3. Impostiamo il progetto in Visual Studio Code

Apriamo Visual Studio Code e selezioniamo la cartella del progetto appena creato

Verrà visualizzato il progetto vuoto appena creato in VS Code

4. Creiamo un installazione di Linux Debian 10 in Virtual Box

Per l’installazione utilizzeremo un immagine iso minimale dato che useremo solo la console e non installeremo nessuna interfaccia grafica

L’immagine iso è prelevabile dal sito ufficiale

https://www.debian.org/CD/netinst/

5. Installiamo il web server nginx

apt update
apt install nginx

avviamo nginx con il comando

service nginx start

e verifichiamo che sia raggiungibile con il browser della macchina host puntando l’ip (ip a per visualizzare le informazioni della scheda di rete)

Per comodità si può configurare un indirizzo ip fisso modificando il file di configurazione /etc/network/interfaces

6. Configuriamo il proxy inverso kestrel

Editiamo e modifichiamo il file di configurazione /etc/nginx/sites-available/default

server {
    listen        80;
    server_name   example.com *.example.com;
    location / {
        proxy_pass         http://localhost:5000;
        proxy_http_version 1.1;
        proxy_set_header   Upgrade $http_upgrade;
        proxy_set_header   Connection keep-alive;
        proxy_set_header   Host $host;
        proxy_cache_bypass $http_upgrade;
        proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header   X-Forwarded-Proto $scheme;
    }
}

server {
    listen   80 default_server;
    # listen [::]:80 default_server deferred;
    return   444;
}

Verifichiamo la sintassi del file di configurazione con il comando

nginx -t

nel caso si riscontrino errori potrebbero essere indicati i numeri delle righe in cui sono presenti (se si utilizza l’editor nano si possono visualizzare, in fase di editing, i numeri delle righe digitando ALT+à)

se non sono presenti errori si può far rileggere il file di configurazione al server

nginx -s reload

7. Installiamo il runtime aspnet core

Aggiungere la chiave di firma del pacchetto Microsoft all’elenco delle chiavi attendibili:

wget https://packages.microsoft.com/config/debian/10/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
dpkg -i packages-microsoft-prod.deb

installiamo il runtime 3.1

apt-get install -y aspnetcore-runtime-3.1
apt-get install -y dotnet-sdk-3.1

8. Installiamo e configuriamo MariaDB

Per installare il database server eseguiamo il comando:

apt install -y mariadb-server

eseguiamo il seguente script per disabilitare l’accesso da remoto per l’utente root

mysql_secure_installation

Change the root password - n
Remove anonymous users - y
Disallow root login remotely – y
Reload privilege tables now – y

Creiamo un nuovo utente con gli stessi privilegi dell’utente root accedendo alla shell del database

mysql

MariaDB [(none)]> GRANT ALL ON *.* TO 'admin'@'192.168.1.%' IDENTIFIED BY 'password' WITH GRANT OPTION;
MariaDB [(none)]> FLUSH PRIVILEGES;
MariaDB [(none)]> exit;

9. Abilitiamo l’accesso remoto al database MariaDB

Di default MariaDB accetta connessioni solo dal localhost quindi controlliamo se è possibile accedere da remoto al database server, con il comando

netstat -an | grep 3306

Se il database risulta in ascolto nel localhost (127.0.0.1) dovremmo modificare il file di configurazione

/etc/mysql/mariadb.conf.d/50-server.cnf 

modificando il valore del bind-address da 127.0.0.1 a 0.0.0.0

Dopo aver effettuato la modifica riavviamo il servizio di MariaDB

systemctl restart mariadb

ed eseguendo nuovamente il comando

netstat -an | grep 3306

controlleremo l’avvenuta modifica

10. Installazione HeidiSQl e accesso al database server

Scarichiamo ed installiamo il client HeidiSQL per accedere al database dall’indirizzo

https://www.heidisql.com/

creiamo una nuova sessione compilando i dati per l’accesso al database server

Nel caso si stia tentando di accedere con l’utente admin e non si riesca ad accedere, bisogna verificare come è stato configurato l’utente.

Al punto 8 abbiamo creato l’utente admin specificando che fa parte della rete 192.168.1.% (% wildcard che indica tutti gli ip) quindi se si sta tentando di accedere da un client di una rete differente, bisogna aggiornare i dettagli dell’utente accedendo alla shell del database server:

mysql

visualizziamo i dati dell’utente admin:

MariaDB [(none)]>SELECT Host, User FROM mysql.user WHERE User=’admin’;

e nel caso aggiorniamo il dettaglio dell’host:

MariaDB [(none)]>UPDATE mysql.user SET Host=’%’ WHERE User=’admin’;

MariaDB [(none)]>FLUSH PRIVILEGES;

11. Creiamo un database di test

Accedendo alla sessione di HeidiSQL creata, clicchiamo con il tasto destro sul nome del server, selezioniamo nuovo database e impostando il nome TestDB

Allo stesso modo, cliccando con il tasto destro del mouse sul nome del database appena creato, creiamo una tabella chiamata Utenti

Cliccando ora con il tasto destro nell’area relativa alle colonne, possiamo creare le colonne:

Creiamo due colonne:

Id – int – not null
Descrizione – varchar – not null

Clicchiamo il tasto Salva per memorizzare le colonne create

12. Creiamo il servizio

Apriamo VS Code e il progetto vuoto precedentemente creato

Impostiamo la connessione al database nel file appsettings.json

Installiamo i pacchetti per utilizzare l’entity framework nel progetto.

Dal menù Terminal di vs code selezioniamo New Terminal e dalla finestra di terminale creata installiamo i seguenti pacchetti:

D:\...\WebApi01> dotnet add package MySql.Data.EntityFrameworkCore
D:\...\WebApi01> dotnet add package Microsoft.EntityFrameworkCore.Design

Utilizziamo il comando dotnet-ef (da netcore 3.0) per la creazione dei files Model del database

D:\...\WebApi01> dotnet-ef dbcontext scaffold "server=IP_SERVER;port=3306;user=admin;password=USER_PASSWORD;database=TestDB" MySql.Data.EntityFrameworkCore -o Models -f

nel progetto verrà creata la cartella Models e i files TestDBContext.cs e Utenti.cs

Nel file TestDBContext.cs viene creata la classe derivata da DbContext dove viene esposta la proprietà DbSet

Nel file Utenti.cs viene creata la classe che rappresenta gli oggetti presenti nel database

Nel file TestDBContext.cs c’è un warning relativo alla stringa di connessione che espone in chiaro la password dell’utente, per la connessione. Possiamo cancellare tutto il metodo OnConfiguring dato che la stringa di connessione al database l’abbiamo impostata nell’appsettings.json e configureremo la connessione nel file Startup.cs

File Startup.cs

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using WebApi01.Models;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;

namespace WebApi01
{
    public class Startup
    {

        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers();
            services.AddDbContext<TestDBContext>(options =>
            options.UseMySQL(Configuration.GetConnectionString("DefaultConnection")));
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseRouting();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
    }
}

File TestController.cs

using Microsoft.AspNetCore.Mvc;
using WebApi01.Models;
using System.Linq;

namespace WebApi01.Controllers
{

    [ApiController]
    [Route("api/test")]
    public class TestController : ControllerBase
    {

        private TestDBContext dBContext;

        // L'instanza di DbContext è passata via dependency injection
        public TestController(TestDBContext context)
        {
            this.dBContext = context;
        }

        [HttpGet]
        public IActionResult test()
        {
            return Ok(dBContext.Utenti.ToList());
        }

    }
}

File Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

namespace WebApi01
{
    public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>()
                    .UseUrls(new[] {"http://0.0.0.0:5001"});
                });
    }
}

13 Aggiorniamo il database

dotnet-ef migrations add CreateIdentityModels
dotnet-ef database update

14. Pubblichiamo l’applicazione

dotnet publish -c Release -r linux-x64

Copiamo i files presenti nella cartella

D:\..\WebApi01\bin\Release\netcoreapp3.1\linux-x64\publish

nella directory del server

/var/www/webapi01

15. Creiamo il servizio Linux

nano /etc/systemd/system/kestrel-webapi01.service

[Unit]
Description=Example .NET Web API App running on Ubuntu

[Service]
WorkingDirectory=/var/www/helloapp
ExecStart=/usr/bin/dotnet /var/www/helloapp/helloapp.dll
Restart=always
# Restart service after 10 seconds if the dotnet service crashes:
RestartSec=10
KillSignal=SIGINT
SyslogIdentifier=dotnet-example
User=www-data
Environment=ASPNETCORE_ENVIRONMENT=Production
Environment=DOTNET_PRINT_TELEMETRY_MESSAGE=false

[Install]
WantedBy=multi-user.target

avviamo il servizio

systemctl start kestrel-helloapp.service

il servizio creato è raggiungibile all’indirizzo

http://192.168.1.184:5001/api/test

è possibile controllare lo stato del servizio con il comando

systemctl status kestrel-helloapp.service

RIFERIMENTI:

https://docs.microsoft.com/it-it/aspnet/core/host-and-deploy/linux-nginx?view=aspnetcore-3.1

https://docs.microsoft.com/it-it/dotnet/core/install/linux-debian

https://www.digitalocean.com/community/tutorials/how-to-install-mariadb-on-debian-10

https://webdock.io/en/docs/how-guides/how-enable-remote-access-your-mariadbmysql-database

https://docs.microsoft.com/it-it/dotnet/core/deploying/

Byte[] To Image

public static System.Windows.Controls.Image ByteArrayToImage(byte[] bytesImg)
{
	System.Windows.Media.Imaging.BitmapImage bitmapImage = new System.Windows.Media.Imaging.BitmapImage();
	bitmapImage.BeginInit();
	bitmapImage.CacheOption = System.Windows.Media.Imaging.BitmapCacheOption.OnLoad;
	bitmapImage.StreamSource = new MemoryStream(bytesImg);
	bitmapImage.EndInit();

	System.Windows.Controls.Image img = new System.Windows.Controls.Image();
	img.Source = bitmapImage;

	return img;
}

Image To Byte[]

public static byte[] BitmapImageToByteArray(System.Windows.Controls.Image img)
{
	byte[] ImgTemp;

	System.Windows.Media.Imaging.BitmapImage bitmapImage = new System.Windows.Media.Imaging.BitmapImage();
	bitmapImage = ((System.Windows.Media.Imaging.BitmapImage)img.Source);

	System.Windows.Media.Imaging.JpegBitmapEncoder encoder = new System.Windows.Media.Imaging.JpegBitmapEncoder();
	encoder.Frames.Add(System.Windows.Media.Imaging.BitmapFrame.Create(bitmapImage));
	using (MemoryStream ms = new MemoryStream())
	{
		encoder.Save(ms);
		ImgTemp = ms.ToArray();
	}

	return ImgTemp;
}

Classi base e derivate

Esempio di classe base (Character) e classe derivata (Creature).
La classe base è astratta perchè contiene una funzione virtuale pura (Jump).
La funzione Jump deve quindi essere implementata nelle classi derivate.

Header file classe base Character

Character.h

#pragma once

#include <string>
using namespace std;

class Character
{
public:
	Character();
	virtual ~Character();
	void walk();
	virtual void jump() = 0;

private:
	string name;
	int hp;
	int ap;
};

Source file classe base Character

Character.cpp

#include <iostream>
#include "Character.h"

using namespace std;

Character::Character()
{
	name = "Character";
	hp = 100;
	ap = 10;

	cout << "Costruttore classe base" << endl;
}

Character::~Character() 
{
	// virtuale
}

void Character::walk()
{
	// classe base walk
	cout << "Classe base Character, funzione walk" << endl;
}

void Character::jump()
{
	// virtuale pura
}

Header file classe derivata Creature

Creature.h

#pragma once

#include "Character.h"

class Creature : public Character
{
public:
	Creature();
	~Creature();
	void jump() override;
};

Source file classe derivata Creature

Creature.cpp

#include <iostream>
#include "Creature.h"

using namespace std;

Creature::Creature()
{
	string name = "Creatura 1";
	int hp = 200;
	int ap = 50;

	cout << "Costruttore classe derivata" << endl;
}

Creature::~Creature()
{
	string name = "Creature dead";
	int hp = 0;
	int ap = 0;
}

void Creature::jump()
{
	// classe derivata jump
	cout << "Classe derivata Creature, funzione jump" << endl;
}

TestClassi.cpp

#include <iostream>
#include "Creature.h"

using namespace std;

int main()
{
	Creature creature;
	
	creature.jump();
	creature.walk();

	system("pause");
	return 0;
}

Output del programma:
Costruttore classe base
Costruttore classe derivata
Classe derivata Creature, funzione Jump
Classe base Character, funzione Walk

Renderfarm

data 07.09.2008
_______________

Per permetere a client diskless di essere avviati tramite il boot via lan è necessario avere una scheda madre che supporta questa funzione e installare un server da cui i client caricheranno il file system.
Le schede che ho utilizzato io sono Gigabyte GA-73PVM-S2H

Il server di rete dovrà poter assegnare gli ip ai client e quindi inviare i dati necessari all’avvio del sistema operativo scelto (debian/linux in questo caso).

Una volta installato un sistema minimale bisognerà installare i servizi di cui abbiamo bisogno e cioè:
server dhcp per poter assegnare gli ip ai client
server tftp per inviare i dati necessari a far fare il boot ai client (è un server ftp minimale che non richiede autenticazione ed utilizza il protocollo udp)
server nfs che permette di condividere directory e files con altri sistemi in rete

Prima di iniziare le installazioni dei vari servizi, aggiorniamo il database locale dei pacchetti debian,
dalla shell:
apt-get update

INSTALLAZIONE E CONFIGURAZIONE SERVER TFTP
apt-get install tftpd-hpa
appena installato il pacchetto bisogna solo attivare il servizio dal file di configurazione
/etc/default/tftpd-hpa
e l’opzione da modificare è RUN_DAEMON. Basta impostarla su ‘yes’, di default è impostata su ‘no’.
RUN_DAEMON=”yes”
ora basta attivare il servizio digitando
/etc/init.d/tftpd-hpa start

INSTALLAZIONE E CONFIGURAZIONE SERVER DHCP
apt-get install dhcp3-server
ora passiamo alla configurazione editando il file
/etc/dhcp3/dhcpd.conf
bisogna aggiungere queste righe

option domain-name-servers 212.216.112.112, 62.31.112.39;
default-lease-time 86400;
max-lease-time 604800;
authoritative;

subnet 192.168.0.0 netmask 255.255.255.0 {
range 192.168.0.200 192.168.0.210;
filename “pxelinux.0”;
next-server 192.168.0.2;
option subnet-mask 255.255.255.0;
option root-path “192.168.0.2:/pxeroot”;
option broadcast-address 192.168.0.255;
option routers 192.168.0.1;
}

Gli ip 212.216.112.112 e 62.31.112.39 sono semplicemente ip di due dns server, potete metterci i dns server che preferite.
192.168.0.0 è la mia rete privata
con l’opzione range si specificano gli ip che il server dhcp può assegnare ai client
il file pxelinux.0 è il PXE bootloader (pxe è il protocollo che permette ai client di eseguire il boot via ethernet)
192.168.0.2 è l’ip del server che stiamo configurando e nella riga successiva c’è la relativa subnet-mask
l’option root-path sarà la directory dove andremo a copiare tutti i file necessari per avviare i client

avviamo il dhcp server digitando il comando
/etc/init.d/dhcp3-server start

creiamo la directory pxeroot
mkdir /pxeroot
entriamo nella directory
cd /pxeroot
e quindi scarichiamo i file per un sistema minimale
debootstrap –arch i386 sid /pxeroot
sid è il nome della unstable debian attuale.
Ho dovuto installare questa versione perchè con le schede madri che ho utilizzato ho dovuto utilizzare l’ultimo kernel disponibile (2.6.26-1-686)

Finita l’installazione del sistema minimale copio i files interfaces, hosts e fstab dal sistema che sto utilizzando al sistema che caricheranno i client e poi li modifico
cp /etc/network/interfaces /pxeroot/etc/network/interfaces
cp /etc/hosts /pxeroot/etc/hosts
cp /etc/fstab /pxeroot/etc/fstab

il file di configurazione interfaces dovrà contenere le seguenti righe

auto lo
iface lo inet loopback

auto eth0
iface eth0 inet dhcp

il file hosts dovrà contenere questa riga

127.0.0.1 localhost pxeboot

e il contenuto del file fstab dovrà essere uguale a queste righe

# /etc/fstab: static file system information.
# /dev/ram0 / ext2 defaults 0 0
proc /proc proc defaults 0 1
tmpfs /tmp tmpfs defaults 0 1

PERSONALIZZAZIONE DEL SISTEMA DEI CLIENT
dobbiamo ora “chiuderci” dentro la directory pxeroot ed installare il kernel
digitiamo
chroot /pxeroot
e poi
apt-get install linux-image-2.6.26-1-686
quindi usciamo digitando
exit

CONFIGURAZIONE PXE
entriamo nella directory tftpboot
cd /var/lib/tftpboot
e quindi scarichiamo il file pxelinux.0
wget http://ftp.debian.org/debian/dists/etch/main/installer-i386/current/images/netboot/pxelinux.0
quindi copiamo il file vmlinuz e initrd.img sempre nella directory tftpboot
cp /pxeroot/vmlinux ./
cp /pxeroot/initrd.img ./

ora creiamo il file di configurazione in cui è contenuta la lista dei kernel disponibili per il boot
mkdir /var/lib/tftpboot/pxelinux.cfg
touch /var/lib/tftpboot/pxelinux.cfg/default

questo è il contenuto del file default

DEFAULT linux

LABEL linux
kernel vmlinuz
append vga=normal initrd=initrd.img ramdisk_size=14332 root=/dev/nfs nfsroot=192.168.0.2:/pxeroot rw —

PROMPT 0
TIMEOUT 0

INSTALLAZIONE E CONFIGURAZIONE SERVER NFS

apt-get install nfs-kernel-server

editiamo e modifichiamo come segue il file /etc/exports
/pxeroot 192.168.0.0/255.255.255.0(rw,sync,no_root_squash,no_subtree_check)

riavviamo il servizio
/etc/init.d/nfs-kernel-server restart

ora dobbiamo modificare un’opzione nella directory del client, per indicargli che il boot dovrà avvenire via network (nfs) e non in locale
il file da modificare è
/pxeroot/etc/initramfs-tools/initramfs.conf

e l’opzione da modificare è “BOOT”
“BOOT=nfs”

RICOMPILAZIONE KERNEL
Per fare il boot via rete ho dovuto ricompilare il kernel perchè non c’erano attivate delle opzioni necessarie.

Per ricompilare il kernel è necessario installare vari pacchetti:
apt-get install debhelper module-init-tools kernel-package libncurses5-dev fakeroot
e i sorgenti del kernel
apt-get install linux-source-2.6.26
quindi bisogna spostarsi nella directory /usr/src in cui troveremo i sorgenti scaricati
cd /usr/src
bzip2 -d linux-source-2.6.26.bz2
tar -xvf linux-source-2.6.26.tar
cd linux-source-2.6.26

copiamo il config installato con il kernel
cp /boot/config-2.6.26-1-686 config

Le opzioni da attivare sono queste:

File systems > Network File Systems > NFS file system support
(CONFIG_NFS_FS=y)

File systems > Network File Systems > Root file system on NFS
(CONFIG_ROOT_NFS=y)

Networking > Networking options > IP: kernel level autoconfiguration
(CONFIG_IP_PNP=y)

Networking > Networking options > IP: DHCP support
(CONFIG_IP_PNP_DHCP=y)

Networking > Networking options > IP: BOOTP support
(CONFIG_IP_PNP_BOOTP=y)

Networking > Networking options > IP: RARP support
(CONFIG_IP_PNP_RARP=y)

andiamo ad attivare le opzioni, digitando
make menuconfig

appena terminato, usciamo e salviamo il file config, quindi
make-kpkg clean

e quindi creiamo il pacchetto .deb (debian) del nuovo kernel creato
fakeroot make-kpkg –append_to_version -486 –initrd –revision=rev.01 kernel_image modules_image

terminata la compilazione usciamo dalla directory ed installiamo il nuovo kernel
cd ..
dpkg -i linux-image-2.6.26-486_rev.01_i386.deb

è importante ricordarsi di copiare il nuovo vmlinuz e initrd.img /generato nella directory /boot) nella directory /var/lib/tftpboot
quindi
cp /boot/vmlinuz-2.6.26-486 /var/lib/tftpboot/vmlinuz
cp /boot/initrd.img-2.6.26-486 /var/lib/tftpboot/initrd.img

ora copiamo e installo il kernel nella directory da cui dovranno avviarsi i client /pxeroot
cp /usr/src/linux-image-2.6.26-486_rev.01_i386.deb /pxeroot/usr/src/linux-image-2.6.26-486_rev.01_i386.deb
ho inoltre copiato la directory dei sorgenti e i files modules
cp usr/src/linux-image-2.6.26-1-686 in /pxeroot/usr/src/linux-image-2.6.26-1-686
cp /proc/modules /pxeroot/proc/modules

dopo aver copiato questi files
chroot /pxeroot
cd /usr/src
dpkg -i linux-image-2.6.26-486_rev.01_i386.deb

INSTALLAZIONE XWINDOWS
chroot /pxeroot
apt-get install x-window-system-core alsa-base alsa-utils
apt-get install gnome-core gdm

finita l’installazione ho provato ad avviare l’x-server (startx) e ho ricevuto quest’errore


/usr/lib/xorg/modules/drivers//vesa_drv.so: undefined symbol: xf86GTFMode

ho trovato un bug segnalato nel pacchetto xserver-xorg-video-vesa
http://bugs.archlinux.org/task/10843

quindi scarico la patch e la applico

creo una directory di lavoro
mkdir /tmp/xserver-xorg-video-vesa
cd /tmp/xserver-xorg-video-vesa
scarico i sorgenti del pacchetto (nel file di configurazione di apt /etc/apt/sources.list deve essere presente la voce deb-src)
apt-get source xserver-xorg-video-vesa

se si riceve un errore del pacchetto mancante dpkg-dev, installarlo
apt-get dpkg-dev

scarico la patch
wget http://bugs.archlinux.org/task/10843?getfile=2259
rinomino il file scaricato
e applico la patch
patch -p1 < /xserver-xorg-video-vesa-2.0.0/src/vesa.c vesa-fix.patch

poi ricreo il pacchetto con la patch applicata
dalla directory /xserver-xorg-video-vesa-2.0.0/
dpkg-buildpackage
se ci sono problemi con le dipendenze usare l’opzione -d (dpkg-buildpackage -d)

se si riceve l’errore
make: dh_testdir: command not found
installare debhelper
apt-get install debhelper

poi
apt-get install pkg-config

se si riceve l’errore no package xorg-server xproto fontsproto installare i seguenti pacchetti
apt-get install xserver-xorg-dev

installo il pacchetto con la patch applicata
dpkg -i xserver-xorg-video-vesa_2.0.0-1_i386.deb
e poi avvio xwindows
startx

ora i client si avviano con l’interfaccia grafica gnome

Riferimenti web
http://www.howtoforge.com/pxe_booting_debian
http://www.debian.org/doc/manuals/reference/ch-kernel.it.html

_______________
data 07.09.2008